- Release status
- Need help?
- Getting started
- Usage guide
- Configuration reference
- Building the SDK
- Contributing
This repository contains the Okta management SDK for Java. This SDK can be used in your server-side code to interact with the Okta management API and:
- Create and update users with the Users API
- Add security factors to users with the Factors API
- Manage groups with the Groups API
- Manage applications with the Apps API
- Much more!
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.
✔️ The current stable major version series is: 1.x
Version | Status |
---|---|
0.0.x | |
1.x | ✔️ Stable |
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.sdk</groupId>
<artifactId>okta-sdk-api</artifactId>
<version>${okta.version}</version>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-impl</artifactId>
<version>${okta.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-httpclient</artifactId>
<version>${okta.version}</version>
<scope>runtime</scope>
</dependency>
For Gradle:
compile "com.okta.sdk:okta-sdk-api:${okta.version}"
runtime "com.okta.sdk:okta-sdk-impl:${okta.version}"
runtime "com.okta.sdk:okta-sdk-httpclient:${okta.version}"
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)
- An API token
Construct a client instance by passing it your Okta domain name and API token:
Client client = Clients.builder()
.setOrgUrl("{yourOktaDomain}")
.setClientCredentials(new TokenClientCredentials("{apiToken}"))
.build();
Hard-coding the Okta domain and API token 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 Client
, you can call methods to make requests to the Okta API.
This library should be used with the Okta management API. For authentication, we recommend using an OAuth 2.0 or OpenID Connect library such as Spring Security OAuth or Okta's Spring Boot integration. For Okta Authentcation API you can use Authentication SDK.
User user = client.getUser("a-user-id");
UserList users = client.listUsers();
// stream
client.listUsers().stream()
.forEach(user -> {
// do something
});
For more examples of handling collections see the paging section below.
// search by email
UserList users = client.listUsers("[email protected]", null, null, null, null);
// filter parameter
users = client.listUsers(null, "status eq \"ACTIVE\"", null, null, null);
User user = UserBuilder.instance()
.setEmail("[email protected]")
.setFirstName("Joe")
.setLastName("Code")
.buildAndCreate(client);
user.getProfile().setFirstName("new-first-name");
user.update();
Custom attributes must first be defined in the Okta profile editor. Then, you can work with custom attributes on a user:
user.getProfile().put("customPropertyKey", "a value");
user.getProfile().get("customPropertyKey");
user.deactivate();
user.delete();
GroupList groups = user.listGroups();
Group group = GroupBuilder.instance()
.setName("a-group-name")
.setDescription("Example Group")
.buildAndCreate(client);
user.addToGroup("groupId");
FactorList factors = user.listFactors();
SmsFactor smsFactor = client.instantiate(SmsFactor.class);
smsFactor.getProfile().setPhoneNumber("555 867 5309");
user.addFactor(smsFactor);
Factor factor = user.getFactor("factorId");
VerifyFactorRequest verifyFactorRequest = client.instantiate(VerifyFactorRequest.class);
verifyFactorRequest.setPassCode("123456");
factor.activate(verifyFactorRequest);
Factor factor = user.getFactor("factorId");
VerifyFactorRequest verifyFactorRequest = client.instantiate(VerifyFactorRequest.class);
verifyFactorRequest.setPassCode("123456");
VerifyFactorResponse response = factor.verify(verifyFactorRequest);
ApplicationList applications = client.listApplications();
Application app = client.getApplication("appId");
SwaApplication swaApp = client.instantiate(SwaApplication.class)
.setSettings(client.instantiate(SwaApplicationSettings.class)
.setApp(client.instantiate(SwaApplicationSettingsApplication.class)
.setButtonField("btn-login")
.setPasswordField("txtbox-password")
.setUsernameField("txtbox-username")
.setUrl("https://example.com/login.html")));
// page through all log events
LogEventList logEvents = client.getLogs();
// or use a filter (start date, end date, filter, or query, sort order) all options are nullable
logEvents = client.getLogs(null, null, null, "interestingURI.com", "ASCENDING");
Not every API endpoint is represented by a method in this library. You can call any Okta management API endpoint using this generic syntax:
// Create an IdP, see: https://developer.okta.com/docs/api/resources/idps#add-identity-provider
ExtensibleResource resource = client.instantiate(ExtensibleResource.class);
ExtensibleResource protocolNode = client.instantiate(ExtensibleResource.class);
protocolNode.put("type", "OAUTH");
resource.put("protocol", protocolNode);
ExtensibleResource result = client.http()
.setBody(resource)
.post("/api/v1/idps", ExtensibleResource.class);
Paging is handled automatically when iterating over a any collection.
// get the list of users
UserList users = client.listUsers();
// get the first user in the collection
log.info("First user in collection: {}", users.iterator().next().getProfile().getEmail());
// or loop through all of them (paging is automatic)
for (User tmpUser : users) {
log.info("User: {}", tmpUser.getProfile().getEmail());
}
// or via a stream
users.stream().forEach(tmpUser -> log.info("User: {}", tmpUser.getProfile().getEmail()));
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 set programmatically (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
token: {apiToken}
requestTimeout: 0 # seconds
rateLimit:
maxRetries: 4
Each one of the configuration values above can be turned into an environment variable name with the _
(underscore) character:
OKTA_CLIENT_CONNECTIONTIMEOUT
OKTA_CLIENT_TOKEN
- 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.token
- 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 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).
By default, a simple production-grade in-memory CacheManager will be enabled when the Client instance is created. This CacheManager implementation has the following characteristics:
- It assumes a default time-to-live and time-to-idle of 1 hour for all cache entries.
- It auto-sizes itself based on your application's memory usage. It will not cause OutOfMemoryExceptions.
The default cache manager is not suitable for an application deployed across multiple JVMs.
This is because the default implementation is 100% in-memory (in-process) in the current JVM. If more than one JVM is deployed with the same application codebase - for example, a web application deployed on multiple identical hosts for scaling or high availability - each JVM would have it's own in-memory cache.
As a result, if your application that uses an Okta Client instance is deployed across multiple JVMs, you SHOULD ensure that the Client is configured with a CacheManager implementation that uses coherent and clustered/distributed memory.
See the ClientBuilder
Javadoc for more details on caching.
If your application is deployed on a single JVM and you still want to use the default CacheManager implementation, but the default cache configuration does not meet your needs, you can specify a different configuration. For example:
Caches.newCacheManager()
.withDefaultTimeToLive(300, TimeUnit.SECONDS) // default
.withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default
.withCache(forResource(User.class) //User-specific cache settings
.withTimeToLive(1, TimeUnit.HOURS)
.withTimeToIdle(30, TimeUnit.MINUTES))
.withCache(forResource(Group.class) //Group-specific cache settings
.withTimeToLive(2, TimeUnit.HOURS))
//... etc ...
.build();
While production applications will usually enable a working CacheManager as described above, you might wish to disable caching entirely. You can do this by configuring a disabled CacheManager instance. For example:
Client client = Clients.builder()
.setCacheManager(Caches.newDisabledCacheManager())
.build();
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.