Okta Java SDK

Authentication LibraryOktaJavaOAuth2OIDCIdentity EngineSDK

Authentication Library

Okta Java SDK

Overview

The Okta Java SDK is the official authentication library for Java applications. It supports both Okta Identity Engine and Classic Engine, providing authentication capabilities through OAuth2, OpenID Connect, and SAML. It consists of two main components: the Management SDK (okta-sdk-java) and Authentication SDK (okta-auth-java), enabling integration with Okta's management API in server-side code and implementation of detailed authentication workflows.

Details

The Okta Java SDK is an actively developed library with the latest version released in July 2024. Key features include support for modern security features through the Identity Engine SDK, Spring Boot integration capabilities, and state machine-based authentication flow management.

The two main SDKs have clearly defined roles. The Management SDK (okta-sdk-java) is used for integration with Okta's management API to manage users, groups, and applications. Meanwhile, the Authentication SDK (okta-auth-java) provides detailed control over authentication workflows but requires more responsibility and maintenance work. For most applications, using Okta's hosted sign-in page or Sign-in Widget is recommended.

After upgrading to Identity Engine, it's recommended to add the latest Identity Engine Java SDK package alongside existing Classic Engine Java libraries.

Pros and Cons

Pros

  • Official Support: Officially provided and maintained by Okta with high reliability
  • Comprehensive Features: Supports major authentication protocols including OAuth2, OIDC, and SAML
  • Identity Engine Support: Compatible with latest Okta platform features
  • Spring Boot Integration: Seamless integration with Spring Boot applications
  • Flexible Implementation: Both management and authentication functionality available in the same environment
  • Active Development: Continuously updated throughout 2024

Cons

  • Complex Configuration: State management complexity when using the Authentication SDK
  • High Learning Cost: Requires understanding of state machine concepts and implementing handlers for each state
  • Maintenance Burden: High maintenance cost when implementing detailed authentication workflows
  • Dependencies: Dependencies on numerous external libraries

Reference Pages

Code Examples

Maven Dependencies Configuration

<!-- Okta Management SDK -->
<dependency>
    <groupId>com.okta.sdk</groupId>
    <artifactId>okta-sdk-api</artifactId>
    <version>19.0.0</version>
</dependency>
<dependency>
    <groupId>com.okta.sdk</groupId>
    <artifactId>okta-sdk-impl</artifactId>
    <version>19.0.0</version>
    <scope>runtime</scope>
</dependency>

<!-- Spring Boot Integration (Recommended) -->
<dependency>
    <groupId>com.okta.spring</groupId>
    <artifactId>okta-spring-sdk</artifactId>
    <version>3.0.7</version>
</dependency>

<!-- Authentication SDK (For advanced control) -->
<dependency>
    <groupId>com.okta.authn.sdk</groupId>
    <artifactId>okta-authn-sdk-api</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>com.okta.authn.sdk</groupId>
    <artifactId>okta-authn-sdk-impl</artifactId>
    <version>2.0.1</version>
    <scope>runtime</scope>
</dependency>

Basic Management SDK Usage Example

import com.okta.sdk.client.Client;
import com.okta.sdk.client.Clients;
import com.okta.sdk.resource.user.User;
import com.okta.sdk.resource.user.UserBuilder;
import com.okta.sdk.resource.user.UserList;

public class OktaManagementExample {
    public static void main(String[] args) {
        // Initialize Okta client
        Client client = Clients.builder()
            .setOrgUrl("https://your-org.okta.com")
            .setClientId("your-client-id")
            .setPrivateKey("path/to/private-key.pem")
            .build();

        // Get user list
        UserList users = client.listUsers();
        users.forEach(user -> {
            System.out.println("User: " + user.getProfile().getLogin());
        });

        // Create new user
        User user = UserBuilder.instance()
            .setEmail("[email protected]")
            .setFirstName("New")
            .setLastName("User")
            .setLogin("[email protected]")
            .setPassword("TempPassword123!".toCharArray())
            .setActive(true)
            .buildAndCreate(client);

        System.out.println("Created user: " + user.getId());
    }
}

Spring Boot Configuration Example

// application.properties
/*
okta.oauth2.issuer=https://your-org.okta.com/oauth2/default
okta.oauth2.client-id=your-client-id
okta.oauth2.client-secret=your-client-secret
okta.oauth2.redirect-uri=/authorization-code/callback
okta.oauth2.post-logout-redirect-uri=http://localhost:8080/
*/

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2 -> oauth2
                .defaultSuccessUrl("/dashboard", true)
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt.decoder(jwtDecoder()))
            );
        return http.build();
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        return OktaJwtDecoder.create(
            "https://your-org.okta.com/oauth2/default"
        );
    }
}

Detailed Authentication Control Using Authentication SDK

import com.okta.authn.sdk.client.AuthenticationClient;
import com.okta.authn.sdk.client.AuthenticationClients;
import com.okta.authn.sdk.resource.AuthenticationRequest;
import com.okta.authn.sdk.resource.AuthenticationResponse;

public class OktaAuthenticationExample {
    
    private AuthenticationClient authClient;
    
    public OktaAuthenticationExample() {
        this.authClient = AuthenticationClients.builder()
            .setOrgUrl("https://your-org.okta.com")
            .build();
    }
    
    public void authenticateUser(String username, String password) {
        try {
            AuthenticationRequest request = authClient.instantiate(AuthenticationRequest.class)
                .setUsername(username)
                .setPassword(password.toCharArray());
            
            AuthenticationResponse response = authClient.authenticate(request, null);
            
            switch (response.getStatus()) {
                case SUCCESS:
                    System.out.println("Authentication successful");
                    String sessionToken = response.getSessionToken();
                    // Use sessionToken to create Okta session
                    break;
                    
                case MFA_REQUIRED:
                    System.out.println("MFA authentication required");
                    handleMfaChallenge(response);
                    break;
                    
                case PASSWORD_EXPIRED:
                    System.out.println("Password update required");
                    handlePasswordReset(response);
                    break;
                    
                default:
                    System.out.println("Authentication status: " + response.getStatus());
            }
            
        } catch (Exception e) {
            System.err.println("Authentication error: " + e.getMessage());
        }
    }
    
    private void handleMfaChallenge(AuthenticationResponse response) {
        // MFA factor selection and challenge processing
        response.getFactors().forEach(factor -> {
            System.out.println("Available MFA: " + factor.getFactorType());
        });
    }
    
    private void handlePasswordReset(AuthenticationResponse response) {
        // Password reset processing
        System.out.println("Password reset required");
    }
}

Group and Application Management

import com.okta.sdk.resource.group.Group;
import com.okta.sdk.resource.group.GroupBuilder;
import com.okta.sdk.resource.application.Application;

public class OktaGroupAndAppManagement {
    
    private Client client;
    
    public OktaGroupAndAppManagement(Client client) {
        this.client = client;
    }
    
    public void manageGroups() {
        // Create group
        Group group = GroupBuilder.instance()
            .setName("Developers")
            .setDescription("Development team members")
            .buildAndCreate(client);
        
        // Add user to group
        User user = client.getUser("[email protected]");
        user.addToGroup(group.getId());
        
        // List group members
        group.listUsers().forEach(member -> {
            System.out.println("Group member: " + member.getProfile().getLogin());
        });
    }
    
    public void manageApplications() {
        // Get application list
        client.listApplications().forEach(app -> {
            System.out.println("Application: " + app.getName());
            System.out.println("Status: " + app.getStatus());
        });
        
        // Assign user to specific application
        Application app = client.getApplication("app-id");
        User user = client.getUser("[email protected]");
        app.assignUserToApplication(user);
    }
}

Identity Engine SDK Usage Example

import com.okta.idx.sdk.api.client.IDXAuthenticationWrapper;
import com.okta.idx.sdk.api.response.AuthenticationResponse;
import com.okta.idx.sdk.api.model.AuthenticationOptions;

public class IdentityEngineExample {
    
    private IDXAuthenticationWrapper authWrapper;
    
    public IdentityEngineExample() {
        this.authWrapper = new IDXAuthenticationWrapper(
            "your-client-id",
            "your-client-secret",
            "https://your-org.okta.com",
            "http://localhost:8080/callback"
        );
    }
    
    public void performAuthentication(String username, String password) {
        try {
            AuthenticationOptions authOptions = new AuthenticationOptions(username, password);
            AuthenticationResponse response = authWrapper.authenticate(authOptions, null);
            
            if (response.isLoginSuccessful()) {
                System.out.println("Authentication successful");
                String accessToken = response.getTokenResponse().getAccessToken();
                System.out.println("Access Token: " + accessToken);
            } else {
                System.out.println("Additional authentication step required: " + response.getAuthenticationStatus());
            }
            
        } catch (Exception e) {
            System.err.println("Authentication error: " + e.getMessage());
        }
    }
}

Error Handling and Logging Configuration

import com.okta.sdk.error.ResourceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OktaErrorHandling {
    
    private static final Logger logger = LoggerFactory.getLogger(OktaErrorHandling.class);
    private Client client;
    
    public void handleOktaErrors() {
        try {
            User user = client.getUser("[email protected]");
        } catch (ResourceException e) {
            switch (e.getStatus()) {
                case 404:
                    logger.warn("User not found: {}", e.getMessage());
                    break;
                case 429:
                    logger.warn("Rate limit reached: {}", e.getMessage());
                    // Implement retry logic
                    break;
                case 401:
                    logger.error("Authentication error: {}", e.getMessage());
                    break;
                default:
                    logger.error("Okta error ({}): {}", e.getStatus(), e.getMessage());
            }
        } catch (Exception e) {
            logger.error("Unexpected error: {}", e.getMessage(), e);
        }
    }
}

Configuration File Management

// ~/.okta/okta.yaml
/*
okta:
  client:
    orgUrl: "https://your-org.okta.com"
    token: "your-api-token"
    
# Or environment variables
# OKTA_CLIENT_ORGURL=https://your-org.okta.com
# OKTA_CLIENT_TOKEN=your-api-token
*/

@Configuration
public class OktaConfig {
    
    @Bean
    public Client oktaClient() {
        return Clients.builder()
            .setOrgUrl(System.getenv("OKTA_CLIENT_ORGURL"))
            .setClientId(System.getenv("OKTA_CLIENT_CLIENTID"))
            .setPrivateKey(System.getenv("OKTA_CLIENT_PRIVATE_KEY"))
            .build();
    }
}