### Start Login with Code Auth Flow Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Initiates the login process using the Authorization Code Flow. This will typically open a browser for user authentication. Ensure platform-specific variants are available. ```kotlin val flow = authFlowFactory.createAuthFlow(client) flow.startLogin() val tokens = flow.continueLogin() ``` -------------------------------- ### iOS Setup with IosCodeAuthFlowFactory Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Use `IosCodeAuthFlowFactory` for iOS authentication flows leveraging ASWebAuthenticationSession. No redirect scheme declaration is needed. ```kotlin // In your iOS-specific code (iosMain) val codeAuthFlowFactory = IosCodeAuthFlowFactory() // Create and use auth flow val authFlow = codeAuthFlowFactory.createAuthFlow(client) // For end session flow val endSessionFlow = codeAuthFlowFactory.createEndSessionFlow(client) ``` -------------------------------- ### Authentication Flow - Get Access Tokens Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Implement the OAuth 2.0 Authorization Code Flow. Use the split flow (`startLogin` and `continueLogin`) for Android robustness against activity termination. Customize authentication URLs and token exchange requests. ```kotlin // Simple one-call authentication (may not return if activity is killed on Android) val authFlow = authFlowFactory.createAuthFlow(client) val tokens: AccessTokenResponse = authFlow.getAccessToken() ``` ```kotlin // Recommended: Split flow for Android robustness val authFlow = authFlowFactory.createAuthFlow(client) authFlow.startLogin() // Opens browser val tokens = authFlow.continueLogin() // Call after redirect returns ``` ```kotlin // Access token response contains: println("Access Token: ${tokens.access_token}") println("Token Type: ${tokens.token_type}") // Usually "Bearer" println("Expires In: ${tokens.expires_in} seconds") println("Refresh Token: ${tokens.refresh_token}") println("ID Token: ${tokens.id_token}") println("Scope: ${tokens.scope}") ``` ```kotlin // Handle activity/process termination on Android if (authFlow.canContinueLogin()) { val tokens = authFlow.continueLogin() } ``` ```kotlin // Customize authentication URL and token exchange request val tokens = authFlow.getAccessToken( configureAuthUrl = { parameters.append("prompt", "login") parameters.append("login_hint", "user@example.com") }, configureTokenExchange = { header("X-Custom-Header", "value") } ) ``` -------------------------------- ### Android MainActivity Setup for AuthFlowFactory Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Register the AndroidCodeAuthFlowFactory in your MainActivity's onCreate method to manage authentication flows and handle activity lifecycle events. This setup also includes logic to continue a login flow after process death. ```kotlin // MainActivity.kt class MainActivity : ComponentActivity() { // Single instance - use DI in production apps val codeAuthFlowFactory = AndroidCodeAuthFlowFactory(useWebView = false) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // MUST register in onCreate or earlier codeAuthFlowFactory.registerActivity(this) // Handle login continuation after process death lifecycleScope.launch { val authFlow = codeAuthFlowFactory.createAuthFlow(client) if (authFlow.canContinueLogin()) { try { val tokens = authFlow.continueLogin() // Save tokens and navigate to main screen } catch (e: OpenIdConnectException) { // Handle authentication error } } } } } ``` -------------------------------- ### Integrate OIDC Bearer Token with Ktor HttpClient Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Installs the OIDC Bearer authentication feature into a Ktor HttpClient. Requires tokenStore, refreshHandler, and client instances. ```kotlin HttpClient(engine) { install(Auth) { oidcBearer( tokenStore = tokenStore, refreshHandler = refreshHandler, client = client, ) } } ``` -------------------------------- ### Handle OIDC Redirect in Wasm Application Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/setup-wasm.md This code snippet demonstrates how to set up a routing mechanism in a Wasm application to handle the OIDC redirect. It checks the current path and calls `PlatformCodeAuthFlow.handleRedirect()` when the path starts with '/redirect'. Ensure this logic is only executed in the new instance of your app opened within the login window. ```kotlin fun main() { CanvasBasedWindow(canvasElementId = "wasm-js-app") { val currentPath = window.location.pathname when { currentPath.isBlank() || currentPath == "/" -> { MainView() } currentPath.startsWith("/redirect") -> { LaunchedEffect(Unit) { PlatformCodeAuthFlow.handleRedirect() } } } } } ``` -------------------------------- ### Create OpenIdConnectClient with Discovery Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Configure an OpenIdConnectClient using a discovery URI to automatically fetch endpoints. Ensure clientId and redirectUri are set. PKCE is enabled by default. ```kotlin val client = OpenIdConnectClient(discoveryUri = "https://auth.example.com/.well-known/openid-configuration") { clientId = "my-client-id" clientSecret = "my-client-secret" // optional for public clients scope = "openid profile email" codeChallengeMethod = CodeChallengeMethod.S256 // PKCE enabled by default redirectUri = "myapp://callback" postLogoutRedirectUri = "myapp://logout-callback" } // Discover endpoints (if using discoveryUri) client.discover() ``` -------------------------------- ### Configure OpenID Connect Client Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Create an instance of OpenIdConnectClient with configuration details. If a discovery URI is provided, endpoint configuration can be omitted. ```swift import OpenIdConnectClient let client = OpenIdConnectClient( config: OpenIdConnectClientConfig( discoveryUri: "", endpoints: Endpoints( tokenEndpoint: "", authorizationEndpoint: "", userInfoEndpoint: nil, endSessionEndpoint: "", revocationEndpoint: "" ), clientId: "", clientSecret: "", scope: "openid profile", codeChallengeMethod: .s256, redirectUri: "", postLogoutRedirectUri: "", disableNonce: false ) ) ``` -------------------------------- ### Configure OpenID Connect Client Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Instantiate the OpenIdConnectClient with discovery URI or specific endpoint configurations. Ensure to set client ID, secret, scope, and redirect URIs. ```kotlin val client = OpenIdConnectClient(discoveryUri = "") { endpoints { tokenEndpoint = "" authorizationEndpoint = "" userInfoEndpoint = null endSessionEndpoint = "" } clientId = "" clientSecret = "" scope = "openid profile" codeChallengeMethod = CodeChallengeMethod.S256 redirectUri = "" postLogoutRedirectUri = "" } ``` -------------------------------- ### Configure Authorization URL with Custom Parameters Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Customize the authorization URL with parameters like 'prompt' for re-authentication, 'login_hint' for pre-filled email, 'claims' for specific user information, and IdP-specific parameters. ```kotlin // Custom parameters on authorization URL val tokens = authFlow.getAccessToken( configureAuthUrl = { // Force re-authentication parameters.append("prompt", "login") // Pre-fill email parameters.append("login_hint", "user@example.com") // Request specific claims parameters.append("claims", "{\"id_token\":{\"email\":null}}") // Custom IdP-specific parameters parameters.append("acr_values", "urn:mace:incommon:iap:silver") }, configureTokenExchange = { // Custom headers for token exchange header("X-Client-Version", "1.0.0") } ) ``` -------------------------------- ### Create OpenIdConnectClient with Manual Endpoints Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Manually configure OpenIdConnectClient endpoints for token, authorization, and session management. Alternatively, use baseUrl for a more concise endpoint definition. ```kotlin val clientManual = OpenIdConnectClient { endpoints { tokenEndpoint = "https://auth.example.com/oauth/token" authorizationEndpoint = "https://auth.example.com/oauth/authorize" endSessionEndpoint = "https://auth.example.com/oauth/logout" userInfoEndpoint = "https://auth.example.com/oauth/userinfo" revocationEndpoint = "https://auth.example.com/oauth/revoke" } // Or use baseUrl for cleaner configuration endpoints { baseUrl("https://auth.example.com/oauth/") { tokenEndpoint = "token" authorizationEndpoint = "authorize" endSessionEndpoint = "logout" } } clientId = "my-client-id" scope = "openid profile" redirectUri = "myapp://callback" } ``` -------------------------------- ### Save Tokens using KeychainTokenStore Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Instantiates a KeychainTokenStore and saves tokens. Requires the tokens object to be defined elsewhere. ```swift let tokenstore = KeychainTokenStore() try await tokenstore.saveTokens(tokens: tokens) ``` -------------------------------- ### Add Kotlin Multiplatform OIDC Dependency (libs.versions.toml) Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Configure the library dependency using a libs.versions.toml file for version management. ```toml [versions] oidc = "" [libraries] oidc-appsupport = { module = "io.github.kalinjul.kotlin.multiplatform:oidc-appsupport", version.ref = "oidc" } oidc-okhttp4 = { module = "io.github.kalinjul.kotlin.multiplatform:oidc-okhttp4", version.ref = "oidc" } oidc-ktor = { module = "io.github.kalinjul.kotlin.multiplatform:oidc-ktor", version.ref = "oidc" } ``` -------------------------------- ### Discover OpenID Endpoints Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md If a discovery URI is provided, call the discover() method on the OpenIdConnectClient to automatically retrieve endpoint configurations. ```kotlin val client = OpenIdConnectClient(discoveryUri = "") { // ... other configurations } client.discover() ``` -------------------------------- ### Configure HTTP Client with Custom Headers Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Customize the HTTP client for the OpenIdConnectClient by adding custom plugins, such as intercepting requests to append headers. ```swift let client = OpenIdConnectClient( httpClient: OpenIdConnectClient.companion.DefaultHttpClient.config(block: { config in config.installClientPlugin( name: "customheader", onRequest: { requestBuilder, content in requestBuilder.headers.append(name: "User-Agent", value: "oidcclient") }, onResponse: {_ in}, onClose: {} ) }), config: ... ) ``` -------------------------------- ### Configure OpenID Connect Authenticator for OkHttp Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Set up an OpenID Connect authenticator for OkHttp, providing functions to retrieve and refresh access tokens, handle refresh failures, and customize requests. This is experimental and Android-only. ```kotlin val authenticator = OpenIdConnectAuthenticator { getAccessToken { tokenStore.getAccessToken() } refreshTokens { oldAccessToken -> refreshHandler.refreshAndSaveToken(client, oldAccessToken) } onRefreshFailed { // provided by app: user has to authenticate again } buildRequest { header("AdditionalHeader", "value") // add custom header to all requests } } val okHttpClient = OkHttpClient.Builder() .authenticator(authenticator) .build() ``` -------------------------------- ### Add Swift Package Dependency Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Add this line to your Swift package dependencies to include the OpenIdConnectClient library. ```swift dependencies: [ .package(url: "https://github.com/kalinjul/OpenIdConnectClient.git", exact: "") ], ``` -------------------------------- ### Continue Login Flow on App Restart Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/setup-android.md Call `authFlow.continueLogin()` on application startup if the login flow was interrupted. This is crucial for resuming authentication after the app is terminated and restarted, especially on low-end devices. ```kotlin if (authFlow.canContinueLogin()) { val tokens = authFlow.continueLogin(configureTokenExchange = null) // save tokens } ``` -------------------------------- ### Android Gradle Configuration for Redirect Scheme Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Configure the OIDC redirect URI scheme in your Android project's build.gradle.kts file using manifestPlaceholders. ```kotlin // build.gradle.kts android { defaultConfig { addManifestPlaceholders( mapOf("oidcRedirectScheme" to "myapp") ) } } ``` -------------------------------- ### Configure Redirect Scheme in build.gradle.kts Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/setup-android.md Set the OIDC redirect scheme in your Android app's build.gradle.kts file. Replace '' with your actual URI scheme. ```kotlin android { defaultConfig { addManifestPlaceholders( mapOf("oidcRedirectScheme" to "") ) } } ``` -------------------------------- ### Add Custom Headers/URL Parameters to Calls Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Configure additional HTTP headers or URL parameters for specific client calls like token exchange or session termination using a closure. ```swift try await client.endSession(idToken: idToken) { requestBuilder in requestBuilder.headers.append(name: "X-CUSTOM-HEADER", value: "value") requestBuilder.url.parameters.append(name: "custom_parameter", value: "value") } ``` ```swift // endSession with Web flow (opens browser and handles post_logout_redirect_uri redirect) let factory = CodeAuthFlowFactory_(ephemeralBrowserSession: false) let flow = factory.createAuthFlow(client: client) try await flow.endSession(idToken: "", configureEndSessionUrl: { urlBuilder in }) ``` ```swift try await flow.getAccessToken( configureAuthUrl: { urlBuilder in urlBuilder.parameters.append(name: "prompt", value: "login") }, configureTokenExchange: { requestBuilder in requestBuilder.headers.append(name: "additionalHeaderField", value: "value") } ) ``` -------------------------------- ### Android Manifest Configuration for HTTPS Redirects Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Configure AndroidManifest.xml to handle HTTPS redirect links for authentication, specifying the activity that will process these intents. ```xml // AndroidManifest.xml ``` -------------------------------- ### Customize Authorization and Token Exchange Requests Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Customizes the authorization URL passed to the browser and the token exchange HTTP request using configure closures. ```kotlin val tokens = flow.getAccessToken(configureAuthUrl = { // customize url that is passed to browser for authorization requests parameters.append("prompt", "login") }, configureTokenExchange = { // customize token exchange http request header("additionalHeaderField", "value") }) ``` -------------------------------- ### Token Store - Secure Token Persistence Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Provides secure, concurrency-safe token persistence using platform-specific implementations (EncryptedSharedPreferences on Android, Keychain on iOS). Supports saving, retrieving, observing, and removing individual or all tokens. ```kotlin // Android - use EncryptedPreferences val tokenStore: TokenStore = AndroidEncryptedPreferencesSettingsStore(context) ``` ```kotlin // iOS - use Keychain val tokenStore: TokenStore = IosKeychainTokenStore() ``` ```kotlin // Save tokens after login tokenStore.saveTokens(tokens) ``` ```kotlin // Or save individual tokens tokenStore.saveTokens( accessToken = tokens.access_token, refreshToken = tokens.refresh_token, idToken = tokens.id_token ) ``` ```kotlin // Retrieve tokens val accessToken: String? = tokenStore.getAccessToken() val refreshToken: String? = tokenStore.getRefreshToken() val idToken: String? = tokenStore.getIdToken() ``` ```kotlin // Get all tokens as a single object val oauthTokens: OauthTokens? = tokenStore.getTokens() ``` ```kotlin // Observe token changes with Flow tokenStore.accessTokenFlow.collect { println("Access token changed: $it") } ``` ```kotlin tokenStore.tokensFlow.collect { if (it != null) { println("Logged in with token: ${it.accessToken}") } else { println("Not logged in") } } ``` ```kotlin // Remove tokens on logout tokenStore.removeTokens() ``` ```kotlin // Or remove individual tokens tokenStore.removeAccessToken() tokenStore.removeRefreshToken() tokenStore.removeIdToken() ``` -------------------------------- ### Register Activity with AndroidCodeAuthFlowFactory Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/setup-android.md Instantiate and register your MainActivity with AndroidCodeAuthFlowFactory. Ensure only one instance of the factory exists and it's managed by a scope that persists across Activity destruction, like an Application or ViewModel scope. ```kotlin class MainActivity : ComponentActivity() { // There should only be one instance of this factory. // The flow should also be created and started from an // Application or ViewModel scope, so it persists Activity.onDestroy() e.g. on low memory // and is still able to process redirect results during login. val codeAuthFlowFactory = AndroidCodeAuthFlowFactory(useWebView = false) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) codeAuthFlowFactory.registerActivity(this) } } ``` -------------------------------- ### Save and Retrieve Tokens using TokenStore Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Saves obtained tokens to a persistent store and retrieves the access token. Uses Multiplatform Settings Library for secure storage on iOS and Android. ```kotlin tokenstore.saveTokens(tokens) val accessToken = tokenstore.getAccessToken() ``` -------------------------------- ### Ktor Integration for Bearer Authentication Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Integrates with Ktor HTTP client to automatically handle token injection and refresh for API calls. Requires adding the `oidc-ktor` dependency. Handles refresh failures by clearing tokens. ```kotlin // Add dependency: io.github.kalinjul.kotlin.multiplatform:oidc-ktor: val tokenStore: TokenStore = // ... platform-specific implementation val refreshHandler = TokenRefreshHandler(tokenStore = tokenStore) val httpClient = HttpClient(engine) { install(Auth) { oidcBearer( tokenStore = tokenStore, refreshHandler = refreshHandler, client = client, onRefreshFailed = { exception -> // Handle refresh failure - e.g., navigate to login println("Token refresh failed: ${exception.message}") tokenStore.removeTokens() } ) } } // All requests automatically include Authorization header val response = httpClient.get("https://api.example.com/protected/resource") // Clear tokens from Ktor cache on logout (required due to Ktor caching) httpClient.clearTokens() // Alternative: Manual token loading and refresh configuration val httpClient = HttpClient(engine) { install(Auth) { bearer { loadTokens(tokenStore = tokenStore) refreshTokens( refreshAndSaveTokens = { oldToken -> refreshHandler.refreshAndSaveToken(client, oldToken) }, onRefreshFailed = { e -> tokenStore.removeTokens() } ) } } } ``` -------------------------------- ### Add Custom Headers and Parameters for End Session Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Include custom headers and URL parameters when ending a user's session. This can be used for custom logging or provider-specific parameters. ```kotlin // Custom headers on end session client.endSession(idToken = idToken) { headers.append("X-Custom-Header", "value") url.parameters.append("custom_parameter", "value") } ``` -------------------------------- ### Add Kotlin Multiplatform OIDC Dependency Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Include the library dependency in your commonMain sourceSet or Android dependencies. Optional modules for Ktor and OkHttp are also available. ```kotlin implementation("io.github.kalinjul.kotlin.multiplatform:oidc-appsupport:") implementation("io.github.kalinjul.kotlin.multiplatform:oidc-ktor:") // optional ktor support implementation("io.github.kalinjul.kotlin.multiplatform:oidc-okhttp4:") // optional okhttp support (android only) ``` -------------------------------- ### Synchronized Token Refresh with TokenRefreshHandler Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Handles synchronized token refreshes to ensure thread-safe token updates. Requires an initialized TokenStore and the client. ```kotlin val refreshHandler = TokenRefreshHandler(tokenStore = tokenstore) refreshHandler.refreshAndSaveToken(client, oldAccessToken = token) // thread-safe refresh and save new tokens to store ``` -------------------------------- ### Request Access Token using Code Auth Flow Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Initiate the Authorization Code Grant Flow to obtain access tokens. Ensure proper error handling for the asynchronous operation. ```swift let factory = CodeAuthFlowFactory_(ephemeralBrowserSession: false) let flow = factory.createAuthFlow(client: client) do { let tokens = try await flow.getAccessToken() } catch { print(error) } ``` -------------------------------- ### Refresh Token and End Session Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Use the client instance to refresh an access token using a refresh token or to end the user's session by providing the ID token. ```swift try await client.refreshToken(refreshToken: tokens.refresh_token!) try await client.endSession(idToken: tokens.id_token!) ``` -------------------------------- ### Handle Android Activity Termination During Login Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Mitigates issues with Android activity/process termination during login by registering the activity and checking if login can be continued. Call continueLogin() during your activity's onCreate(). ```kotlin authFlowFactory.registerActivity(this) val flow = authFlowFactory.createAuthFlow(client) if (flow.canContinueLogin()) { val tokens = flow.continueLogin() } ``` -------------------------------- ### Add Custom Headers and URL Parameters to End Session Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Allows adding custom HTTP headers and URL parameters to the end session request. ```kotlin client.endSession(idToken = idToken) { headers.append("X-CUSTOM-HEADER", "value") url.parameters.append("custom_parameter", "value") } ``` -------------------------------- ### Configure Verified App-Links as Redirect URL Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/setup-android.md Modify your AndroidManifest.xml to use HTTPS redirect links instead of custom schemes. This involves updating the intent filter for HandleRedirectActivity to include 'android:autoVerify="true"' and specifying your host. ```xml ``` -------------------------------- ### End Session using Web Flow with Redirect URI Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Initiates an end session flow using a Web Flow, typically after configuring a postLogoutRedirectUri. This helps clear browser cookies. ```kotlin val flow = authFlowFactory.createEndSessionFlow(client) tokens.id_token?.let { flow.endSession(it) } ``` -------------------------------- ### Continue Logout Flow on App Restart Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/setup-android.md Call `endSessionFlow.continueLogout()` on application startup to complete a logout process that was interrupted. This ensures tokens are cleared properly after an application restart. ```kotlin if (endSessionFlow.canContinueLogout()) { endSessionFlow.continueLogout() // clear tokens } ``` -------------------------------- ### OkHttp Integration for Android Authenticator Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Provides an OkHttp Authenticator for Android apps using OkHttp directly. Handles token injection and refresh, allowing custom headers to be added to authenticated requests. Requires `oidc-okhttp4` dependency. ```kotlin // Add dependency: io.github.kalinjul.kotlin.multiplatform:oidc-okhttp4: val authenticator = OpenIdConnectAuthenticator { getAccessToken { tokenStore.getAccessToken() } refreshTokens { oldAccessToken -> refreshHandler.refreshAndSaveToken(client, oldAccessToken) } onRefreshFailed { // Navigate to login screen // This runs on main thread } buildRequest { // Add custom headers to all authenticated requests header("X-App-Version", "1.0.0") header("X-Platform", "Android") } } val okHttpClient = OkHttpClient.Builder() .authenticator(authenticator) .build() // All requests automatically include Bearer token val request = Request.Builder() .url("https://api.example.com/protected/resource") .build() val response = okHttpClient.newCall(request).execute() ``` -------------------------------- ### Token Refresh and Session Management Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Use `OpenIdConnectClient` for silent token refresh and session ending. Supports custom headers and parameters for token refresh requests. Handles browser-based session ending and post-restart logout continuation. ```kotlin // Refresh token val newTokens: AccessTokenResponse = client.refreshToken( refreshToken = tokens.refresh_token!! ) ``` ```kotlin // Refresh with custom headers val newTokens = client.refreshToken(refreshToken = refreshToken) { headers.append("X-Custom-Header", "value") url.parameters.append("custom_param", "value") } ``` ```kotlin // End session via POST request (silent, no browser) val status: HttpStatusCode = client.endSession(idToken = tokens.id_token!!) ``` ```kotlin // End session with browser flow (clears browser cookies) val endSessionFlow = authFlowFactory.createEndSessionFlow(client) endSessionFlow.endSession(idToken = tokens.id_token) ``` ```kotlin // Handle logout continuation after app restart if (endSessionFlow.canContinueLogout()) { endSessionFlow.continueLogout() } ``` ```kotlin // Revoke token (RFC7009) val status = client.revokeToken(token = tokens.access_token) // or revoke refresh token val status = client.revokeToken(token = tokens.refresh_token!!) ``` -------------------------------- ### Add Custom Headers for Token Refresh Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Append custom headers to the token refresh request. Useful for including request IDs or other tracking information. ```kotlin // Custom headers on token refresh val newTokens = client.refreshToken(refreshToken = refreshToken) { headers.append("X-Custom-Header", "value") headers.append("X-Request-ID", UUID.randomUUID().toString()) } ``` -------------------------------- ### Refresh Token and End Session Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Performs token refresh if a refresh token is available and ends the user session using the ID token. ```kotlin tokens.refresh_token?.let { client.refreshToken(refreshToken = it) } tokens.id_token?.let { client.endSession(idToken = it) } ``` -------------------------------- ### Parse JWT Tokens Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/docs/ios/README.md Utilize the JwtParser to parse JWT tokens, such as the ID token, and access its payload claims like audience, issuer, and custom claims. ```swift let jwt = tokens.id_token.map { try! JwtParser.shared.parse(from: $0) } print(jwt?.payload.aud) // print audience print(jwt?.payload.iss) // print issuer print(jwt?.payload.additionalClaims["email"]) // get claim ``` -------------------------------- ### Thread-Safe Token Refresh Handler Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Ensures only one token refresh operation occurs at a time, preventing race conditions. It retrieves the refresh token from the store, calls the client to refresh, and saves the new tokens. ```kotlin val tokenStore: TokenStore = // ... platform-specific implementation val refreshHandler = TokenRefreshHandler(tokenStore = tokenStore) // Thread-safe refresh that saves new tokens to store val newTokens: OauthTokens = refreshHandler.refreshAndSaveToken( client = client, oldAccessToken = currentAccessToken ) // The handler: // 1. Locks to prevent concurrent refresh calls // 2. Checks if token was already refreshed by another call // 3. Retrieves refresh token from store // 4. Calls client.refreshToken() // 5. Saves new tokens to store // 6. Returns new tokens println("New access token: ${newTokens.accessToken}") println("New refresh token: ${newTokens.refreshToken}") println("New ID token: ${newTokens.idToken}") ``` -------------------------------- ### JWT Parsing and Claim Extraction Source: https://context7.com/kalinjul/kotlin-multiplatform-oidc/llms.txt Parses JWT tokens to access header and payload claims without performing validation. Useful for inspecting ID or access tokens. Supports accessing standard and custom claims. ```kotlin // Parse JWT from ID token val jwt: Jwt = Jwt.parse(tokens.id_token!!) // Access header information println("Algorithm: ${jwt.header.alg}") println("Key ID: ${jwt.header.kid}") println("Type: ${jwt.header.typ}") // Access standard claims from payload (IdToken) val payload: IdToken = jwt.payload println("Issuer: ${payload.iss}") println("Subject (User ID): ${payload.sub}") println("Audience: ${payload.aud}") println("Expiration: ${payload.exp}") println("Issued At: ${payload.iat}") println("Auth Time: ${payload.auth_time}") println("Nonce: ${payload.nonce}") // Access custom claims val email = payload.additionalClaims["email"] as? String val name = payload.additionalClaims["name"] as? String val roles = payload.additionalClaims["roles"] as? List println("Email: $email") println("Name: $name") println("Roles: $roles") // Extension function for parsing from String val jwt = tokens.id_token?.parseJwt() ``` -------------------------------- ### Clear Tokens in Ktor Client Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Explicitly clears tokens from the Ktor client, typically called on logout to invalidate tokens outside of Ktor's automatic refresh logic. ```kotlin ktorHttpClient.clearTokens() ``` -------------------------------- ### Parse JWT without Validation Source: https://github.com/kalinjul/kotlin-multiplatform-oidc/blob/main/README.md Parses a JWT token string into a Jwt object for accessing its payload and claims. Note that this method does not perform any validation. ```kotlin val jwt = tokens.id_token?.let { Jwt.parse(it) } println(jwt?.payload?.aud) // print audience println(jwt?.payload?.iss) // print issuer println(jwt?.payload?.additionalClaims?.get("email")) // get claim ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.