Skip to content

Commit

Permalink
feat: add authorization url customization
Browse files Browse the repository at this point in the history
  • Loading branch information
kalinjul committed Jun 18, 2024
1 parent d86b250 commit 0f783b4
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 9 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ client.endSession(idToken = idToken) {
}
```

```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")
})
```

# JWT Parsing
We provide simple JWT parsing (without any validation):
```kotlin
Expand Down
11 changes: 11 additions & 0 deletions docs/ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ try await client.endSession(idToken: idToken) { requestBuilder 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")
}
)
```

# JWT Parsing
We provide simple JWT parsing:
```swift
Expand Down
11 changes: 11 additions & 0 deletions oidc-appsupport/src/androidUnitTest/kotlin/README.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import android.os.Bundle
import androidx.activity.ComponentActivity
import io.ktor.client.request.header
import org.publicvalue.multiplatform.oidc.ExperimentalOpenIdConnect
import org.publicvalue.multiplatform.oidc.OpenIdConnectClient
import org.publicvalue.multiplatform.oidc.appsupport.AndroidCodeAuthFlowFactory
Expand Down Expand Up @@ -75,6 +76,16 @@ object README {
}
}

// Custom parameters in authorization request / exchange token request
suspend fun `Custom auth request`() {
val flow = authFlowFactory.createAuthFlow(client)
val tokens = flow.getAccessToken(configureAuthUrl = {
parameters.append("prompt", "login")
}, configureTokenExchange = {
header("additionalHeaderField", "value")
})
}

// We provide simple JWT parsing
fun `We_provide_simple_JWT_parsing`() {
val tokens = AccessTokenResponse("abc")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.publicvalue.multiplatform.oidc.flows

import io.ktor.client.request.HttpRequestBuilder
import io.ktor.http.URLBuilder
import org.publicvalue.multiplatform.oidc.OpenIdConnectClient
import org.publicvalue.multiplatform.oidc.OpenIdConnectException
import org.publicvalue.multiplatform.oidc.types.AuthCodeRequest
Expand Down Expand Up @@ -29,7 +30,7 @@ abstract class CodeAuthFlow(val client: OpenIdConnectClient) {
*/
@Suppress("unused")
@Throws(CancellationException::class, OpenIdConnectException::class)
suspend fun getAccessToken(): AccessTokenResponse = getAccessToken(null)
suspend fun getAccessToken(): AccessTokenResponse = getAccessToken(null, null)

/**
* Start the authorization flow to request an access token.
Expand All @@ -39,12 +40,30 @@ abstract class CodeAuthFlow(val client: OpenIdConnectClient) {
*/
@Suppress("unused")
@Throws(CancellationException::class, OpenIdConnectException::class)
suspend fun getAccessToken(configure: (HttpRequestBuilder.() -> Unit)? = null): AccessTokenResponse = wrapExceptions {
@Deprecated(
message = "Use getAccessToken(configureAuthUrl, configureTokenExchange) instead",
replaceWith = ReplaceWith("getAccessToken(configureAuthUrl = null, configureTokenExchange = configure)")
)
suspend fun getAccessToken(configure: (HttpRequestBuilder.() -> Unit)? = null): AccessTokenResponse = getAccessToken(null, configure)

/**
* Start the authorization flow to request an access token.
*
* @param configureAuthUrl configuration closure to configure the auth url passed to browser
* @param configureTokenExchange configuration closure to configure the http request builder with (will _not_
* be used for discovery if necessary)
*/
@Suppress("unused")
@Throws(CancellationException::class, OpenIdConnectException::class)
suspend fun getAccessToken(
configureAuthUrl: (URLBuilder.() -> Unit)? = null,
configureTokenExchange: (HttpRequestBuilder.() -> Unit)? = null
): AccessTokenResponse = wrapExceptions {
if (!client.config.discoveryUri.isNullOrEmpty()) {
client.discover()
}
val request = client.createAuthorizationCodeRequest()
return getAccessToken(request, configure)
val request = client.createAuthorizationCodeRequest(configureAuthUrl)
return getAccessToken(request, configureTokenExchange)
}

private suspend fun getAccessToken(request: AuthCodeRequest, configure: (HttpRequestBuilder.() -> Unit)?): AccessTokenResponse {
Expand Down
25 changes: 21 additions & 4 deletions sample-app/ios-app/iosApp/Readme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,31 @@ struct Readme {

// Perform refresh or endSession:
func _3() async throws {
try await client.refreshToken(refreshToken: "") { builder in
builder.headers.append(name: "Accept", value: "application/json")
builder.build()
}
try await client.refreshToken(refreshToken: tokens.refresh_token!)
try await client.endSession(idToken: tokens.id_token!)
}

// customize endSession request:
func _3a() async throws {
try await client.endSession(idToken: "") { requestBuilder in
requestBuilder.headers.append(name: "X-CUSTOM-HEADER", value: "value")
requestBuilder.url.parameters.append(name: "custom_parameter", value: "value")
}
}

// customize getAccessToken request:
func _3b() async throws {
let flow = CodeAuthFlow(client: client)
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:
func _4() {
let jwt = tokens.id_token.map { try! JwtParser.shared.parse(from: $0) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ class HomePresenter(
if (client != null) {
scope.launch {
catchErrorMessage {
val newTokens = authFlowFactory.createAuthFlow(client).getAccessToken()
val newTokens = authFlowFactory.createAuthFlow(client).getAccessToken(
configureAuthUrl = {
parameters.append("prompt", "login")
}
)
updateTokenResponse(newTokens)
}
}
Expand Down

0 comments on commit 0f783b4

Please sign in to comment.