- Release status
- Need help?
- Getting started
- Usage guide
- Configuration reference
- Building the SDK
- Contributing
The Okta Authentication SDK is a convenience wrapper around Okta's Authentication API.
This SDK is a convenient HTTP client wrapper for Okta's Authentication API. These APIs are powerful and useful if you need to achieve one of these cases:
- You have an existing application that needs to accept primary credentials (username and password) and do custom logic before communicating with Okta.
- You have significantly custom authentication workflow or UI needs, such that Okta’s hosted sign-in page or Sign-In Widget do not give you enough flexibility.
The power of this SDK comes with more responsibility and maintenance: you will have to design your authentication workflow and UIs by hand, respond to all relevant states in Okta’s authentication state machine, and keep up to date with new features and states in Okta.
Otherwise, most applications can use the Okta hosted sign-in page or the Sign-in Widget. For these cases, you should use Okta's Spring Boot Starter, Spring Security or other OIDC/OAuth 2.0 library.
Okta's Authentication API is built around a state machine. In order to use this library you will need to be familiar with the available states. You will need to implement a handler for each state you want to support.
We also publish these libraries for Java:
You can learn more on the Okta + Java page in our documentation.
This library uses semantic versioning and follows Okta's library version policy.
Version | Status |
---|---|
1.x | |
2.x.x | ✔️ Stable (migration guide) |
The latest release can always be found on the releases page.
If you run into problems using the SDK, you can
- Ask questions on the Okta Developer Forums
- Post issues here on GitHub (for code errors)
To use this SDK you will need to include the following dependencies:
For Apache Maven:
<dependency>
<groupId>com.okta.authn.sdk</groupId>
<artifactId>okta-authn-sdk-api</artifactId>
<version>${okta.authn.version}</version>
</dependency>
<dependency>
<groupId>com.okta.authn.sdk</groupId>
<artifactId>okta-authn-sdk-impl</artifactId>
<version>${okta.authn.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-httpclient</artifactId>
<version>${okta.sdk.version}</version>
<scope>runtime</scope>
</dependency>
For Gradle:
compile 'com.okta.authn.sdk:okta-authn-sdk-api:${okta.authn.version}'
runtime 'com.okta.authn.sdk:okta-authn-sdk-impl:${okta.authn.version}'
runtime 'com.okta.sdk:okta-sdk-httpclient:${okta.sdk.version}'
where ${okta.authn.version} is the latest published version in Maven Central and ${okta.sdk.version} is the latest published version in Maven Central.
Snapshots are deployed off of the 'master' branch to OSSRH and can be consumed using the following repository configured for Apache Maven or Gradle:
https://oss.sonatype.org/content/repositories/snapshots/
You'll also need:
- An Okta account, called an organization (sign up for a free developer organization if you need one)
Construct a client instance by passing it your Okta domain name and API token:
AuthenticationClient client = AuthenticationClients.builder()
.setOrgUrl("https://{yourOktaDomain}")
.build();
Hard-coding the Okta domain works for quick tests, but for real projects you should use a more secure way of storing these values (such as environment variables). This library supports a few different configuration sources, covered in the configuration reference section.
These examples will help you understand how to use this library. You can also browse the full API reference documentation.
Once you initialize a AuthenticationClient
, you can call methods to make requests to the Okta Authentication API. To call other Okta APIs, see the Management SDK.
An authentication flow usually starts with a call to authenticate
:
// could be where to redirect when authentication is done, a token, or null
String relayState = "/application/specific";
client.authenticate(username, password, relayState, stateHandler);
Everything looks pretty standard except for stateHandler
. The AuthenticationStateHandler
is a mechanism to fire an event for the given authentication state returned. Basically, it prevents you from needing to use something like a switch statement to check state of the AuthenticationResponse
.
A typical AuthenticationStateHandler
may look something like:
public class ExampleAuthenticationStateHandler extends AuthenticationStateHandlerAdapter {
@Override
public void handleUnknown(AuthenticationResponse unknownResponse) {
// redirect to "/error"
}
@Override
public void handleSuccess(AuthenticationResponse successResponse) {
// a user is ONLY considered authenticated if a sessionToken exists
if (Strings.hasLength(successResponse.getSessionToken())) {
String relayState = successResponse.getRelayState();
String dest = relayState != null ? relayState : "/";
// redirect to dest
}
// other state transition successful
}
@Override
public void handlePasswordExpired(AuthenticationResponse passwordExpired) {
// redirect to "/login/change-password"
}
// Other implemented states here
}
As noted in the above example, a user is ONLY considered authenticated if AuthenticationResponse.getSessionToken()
is not null. This sessionToken
can be exchanged via the Okta Sessions API to start an SSO session, but that is beyond the scope of this library.
NOTE: UNKNOWN
is not an actual state in Okta's state model. The method handleUnknown is called when an unimplemented or unrecognized state is reached. This could happen if:
- Your handler doesn't have an implementation for the state that was just returned
- Your Okta organization configuration changed, and a new state is now possible (for example, an admin turned on multi-factor authentication)
- Okta added something new to the state model entirely
This library looks for configuration in the following sources:
- An
okta.yaml
at the root of the applications classpath - An
okta.yaml
file in a.okta
folder in the current user's home directory (~/.okta/okta.yaml
or%userprofile\.okta\okta.yaml
) - Environment variables
- Java System Properties
- Configuration explicitly passed to the constructor (see the example in Getting started)
Higher numbers win. In other words, configuration passed via the constructor will override configuration found in environment variables, which will override configuration in okta.yaml
(if any), and so on.
The full YAML configuration looks like:
okta:
client:
connectionTimeout: 30 # seconds
orgUrl: "https://{yourOktaDomain}" # i.e. https://dev-123456.oktapreview.com
proxy:
port: null
host: null
username: null
password: null
requestTimeout: 10 # seconds
rateLimit:
maxRetries: 2
Each one of the configuration values above can be turned into an environment variable name with the _
(underscore) character:
OKTA_CLIENT_CONNECTIONTIMEOUT
OKTA_CLIENT_RATELIMIT_MAXRETRIES
- and so on
Each one of of the configuration values written in 'dot' notation to be used as a Java system property:
okta.client.connectionTimeout
okta.client.rateLimt.maxRetries
- and so on
By default this SDK will retry requests that are return with a 503
, 504
, 429
, or socket/connection exceptions. To disable this functionality set the properties okta.client.requestTimeout
and okta.client.rateLimit.maxRetries
to 0
.
Setting only one of the values to zero will disable that check. Meaning, by default, four retry attempts will be made. If you set okta.client.requestTimeout
to 45
seconds and okta.client.rateLimit.maxRetries
to 0
. This SDK will continue to retry indefinitely for 45
seconds. If both values are non zero, this SDK will attempt to retry until either of the conditions are met (not both).
All of the AuthenticationClient
requests allow setting additional HTTP headers and query parameters. This is useful in a variety of situations:
- Device Finterprinting
- Setting the
X-Forwarded-For
header - Setting additional query paramters that have not been added to the SDK yet
Create a RequestContext
object, and include it as a method parameter when using the AuthenticationClient
.
List<Header> headers = new ArrayList<>();
// set any header
headers.add(new Header("aHeaderName", "aValue"));
// X-Forwarded-For
headers.add(Header.xForwardedFor("10.10.0.1"));
// X-Device-Fingerprint
headers.add(Header.xDeviceFingerprint("your-finger-print"));
List<QueryParameter> queryParameters = new ArrayList<>();
// set query param
queryParameters.add(new QueryParameter("aQueryParam", "aValue"));
RequestContext requestContext = new RequestContext(headers, queryParameters);
In most cases, you won't need to build the SDK from source. If you want to build it yourself, take a look at the build instructions wiki (though just cloning the repo and running mvn install
should get you going).
We're happy to accept contributions and PRs! Please see the contribution guide to understand how to structure a contribution.