Library for using OpenID Connect in iOS Projects. Build with kotlin multiplatform, published for iOS as Swift Package. This project aims to be a lightweight implementation without sophisticated validation on client side. This iOS Framework is generated from the kotlin-multiplatform-oidc project, where you can find the source code.
- Currently, it only supports the Authorization Code Grant Flow.
- Support for discovery via .well-known/openid-configuration.
- Support for PKCE
- Uses
ASWebAuthenticationSession
- Simple JWT parsing
Add the swift package from https://github.com/kalinjul/OpenIdConnectClient. If you're using a swift module, add this line:
dependencies: [
.package(url: "https://github.com/kalinjul/OpenIdConnectClient.git", exact: "0.9.1")
],
Create OpenID config and client:
import OpenIdConnectClient
let client = OpenIdConnectClient(
config: OpenIdConnectClientConfig(
discoveryUri: "<discovery url>",
endpoints: Endpoints(
tokenEndpoint: "<tokenEndpoint>",
authorizationEndpoint: "<authorizationEndpoint>",
userInfoEndpoint: nil,
endSessionEndpoint: "<endSessionEndpoint>"
),
clientId: "<clientId>",
clientSecret: "<clientSecret>",
scope: "openid profile",
codeChallengeMethod: .s256,
redirectUri: "<redirectUri>"
)
)
If you provide a Discovery URI, you may skip the endpoint configuration and set endpoints to nil. If required, you can also configure the http client with custom headers etc:
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: ...
)
Request access token using code auth flow:
let flow = CodeAuthFlow(client: client)
do {
let tokens = try await flow.getAccessToken()
} catch {
print(error)
}
Perform refresh or endSession:
try await client.refreshToken(refreshToken: tokens.refresh_token!)
try await client.endSession(idToken: tokens.id_token!)
For most calls (getAccessToken()
, refreshToken()
, endSession()
), you may provide
additional configuration for the http call, like headers or parameters using the configure closure parameter:
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")
}
try await flow.getAccessToken(
configureAuthUrl: { urlBuilder in
urlBuilder.parameters.append(name: "prompt", value: "login")
},
configureTokenExchange: { requestBuilder in
requestBuilder.headers.append(name: "additionalHeaderField", value: "value")
}
)
We provide simple JWT parsing:
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
Since persisting tokens is a common task in OpenID Connect Authentication, we provide a
TokenStore
that uses a Multiplatform Settings Library
to persist tokens in Keystore.
let tokenstore = KeychainTokenStore()
try await tokenstore.saveTokens(tokens: tokens)