OpenID Connect Authentication

Authentication follows the Authorization Code Flow with PKCE — the recommended flow for mobile apps, as defined in RFC 6749arrow-up-right and RFC 7636arrow-up-right. For a detailed protocol reference, see the OpenID Connect Core 1.0 specarrow-up-right.

1

Authorization Request

The app opens a secure system browser and redirects the user to the Identity Provider (e.g. Keycloak). A PKCE code_challenge is included so the token exchange can later be verified.

2

Callback

After the user authenticates, the Identity Provider redirects back to the app via a custom URI scheme or App/Universal Link, carrying a short-lived authorization_code.

3

Token Request

The app exchanges the authorization_code — together with the PKCE code_verifier — for an access_token, id_token, and optionally a refresh_token.

circle-info

Since mobile apps are public clients (no client_secret), PKCE is mandatory.


Implementation

The recommended library for both platforms is AppAuth, a certified OpenID Connect implementation maintained by the OpenID Foundation:

Platform
Library
Minimum OS

AppAuth handles PKCE, endpoint discovery, and the secure browser session automatically — iOS uses ASWebAuthenticationSession, Android uses Chrome Custom Tabs.

Installation

https://github.com/openid/AppAuth-iOS

Redirect URI — Info.plist

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>com.example.app</string>
    </array>
  </dict>
</array>

Login

import AppAuth

class AuthManager {

    // Retain the session to keep ASWebAuthenticationSession alive
    var currentAuthFlow: OIDExternalUserAgentSession?

    func login(presenting viewController: UIViewController) {
        // Get the Authentication URL from the SDK
        guard let openIDBaseUrl = URL(string:kapeSDK?.manager.getConfiguration().domains().getOpenidApiDomain() ?? "") else { return }

        // 1. Discover AS endpoints
        OIDAuthorizationService.discoverConfiguration(forIssuer: openIDBaseUrl) { configuration, error in
            guard let configuration else {
                print("Discovery failed: \(error!)")
                return
            }

            // 2. Build authorization request — PKCE is handled automatically
            let request = OIDAuthorizationRequest(
                configuration: configuration,
                clientId: "my-mobile-app",
                // use offline_access to request long-living Refresh Tokens
                scopes: [OIDScopeOpenID, OIDScopeProfile, OIDScopeEmail, "offline_access"],
                redirectURL: URL(string: "com.example.app:/callback")!,
                responseType: OIDResponseTypeCode,
                additionalParameters: nil
            )

            // 3. Open ASWebAuthenticationSession and exchange code for tokens
            self.currentAuthFlow = OIDAuthState.authState(
                byPresenting: request,
                presenting: viewController
            ) { authState, error in
                guard let authState else {
                    print("Auth failed: \(error!)")
                    return
                }
                let credentials = AuthCredentials(
                    accessToken: authState.lastTokenResponse?.accessToken ?? "",
                    refreshToken: authState.lastTokenResponse?.refreshToken ?? "",
                    idToken: authState.lastTokenResponse?.idToken ?? ""
                )
                try kapeSDK!.manager.identity().openidAuthenticateWithAuthCredentials(authCredentials: credentials)
            }
        }
    }
}
triangle-exclamation

Hold a strong reference to currentAuthFlow for the duration of the session. Releasing it cancels the ASWebAuthenticationSession.


Terminating an OpenID SSO Session

The authentication request will usually initiate an SSO Session, which will ensure that other apps using the same authorization URL can use the session to automatically log in the user. If you want to terminate such a session — preventing other apps from getting automatically logged in — you need to create an EndSessionRequest instead of AuthorizationRequest, providing the ID Token which you can fetch from the SDK with fetchTokenTypeType.


Login Hint (Cross-App SSO)

The SDK supports cross-app Single Sign-On (SSO) via the standard OpenID Connect login_hint parameter. When a user is already authenticated in one app, another app can obtain a Login Token from the SDK and pass it as login_hint in the Authorization Code Flow with PKCE. The Identity Provider uses this token to recognise the existing session and authenticate the user without requiring them to re-enter their credentials.

Generating a Login Token

Call openidGenerateLoginToken on the SDK's identity module, passing the clientId of the target application. The method returns a short-lived token string. The calling app must already be authenticated; the call will fail otherwise.

How It Works

The Identity Provider uses the login_hint value to look up the existing user session. If the session is still valid, the user is authenticated silently and the authorization code is issued without any additional login prompt. The resulting flow is identical to the standard Authorization Code Flow — the same openidAuthenticateWithAuthCredentials call on the SDK is used to hand the tokens to the SDK.

Last updated