Skip to content

Commit

Permalink
feat(android-sdk): add sign-in options for android sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoyijun committed Sep 6, 2024
1 parent ce2af37 commit 4be3174
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import io.logto.sdk.android.extension.oidcConfigEndpoint
import io.logto.sdk.android.storage.PersistStorage
import io.logto.sdk.android.type.AccessToken
import io.logto.sdk.android.type.LogtoConfig
import io.logto.sdk.android.type.SignInOptions
import io.logto.sdk.android.util.LogtoUtils.expiresAtFrom
import io.logto.sdk.android.util.LogtoUtils.nowRoundToSec
import io.logto.sdk.core.Core
Expand Down Expand Up @@ -83,12 +84,12 @@ open class LogtoClient(
/**
* Sign in
* @param[context] the activity to perform a sign-in action
* @param[redirectUri] one of the redirect URIs of this application
* @param[options] the sign-in options
* @param[completion] the completion which handles the result of signing in
*/
fun signIn(
context: Activity,
redirectUri: String,
options: SignInOptions,
completion: EmptyCompletion<LogtoException>,
) {
getOidcConfig { getOidcConfigException, oidcConfig ->
Expand All @@ -101,7 +102,7 @@ open class LogtoClient(
context = context,
logtoConfig = logtoConfig,
oidcConfig = requireNotNull(oidcConfig),
redirectUri = redirectUri,
signInOptions = options,
) { authException, fetchedTokenResponse ->
authException?.let {
completion.onComplete(it)
Expand Down Expand Up @@ -133,6 +134,22 @@ open class LogtoClient(
}
}

/**
* Sign in
* @param[context] the activity to perform a sign-in action
* @param[redirectUri] one of the redirect URIs of this application
* @param[completion] the completion which handles the result of signing in
*/
fun signIn(
context: Activity,
redirectUri: String,
completion: EmptyCompletion<LogtoException>,
) = signIn(
context = context,
options = SignInOptions(redirectUri = redirectUri),
completion = completion,
)

/**
* Sign out
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ internal object LogtoAuthManager {
}

fun isLogtoAuthResult(uri: Uri) = logtoAuthSession?.let {
uri.toString().startsWith(it.redirectUri)
uri.toString().startsWith(it.signInOptions.redirectUri)
} ?: false
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.net.Uri
import io.logto.sdk.android.completion.Completion
import io.logto.sdk.android.exception.LogtoException
import io.logto.sdk.android.type.LogtoConfig
import io.logto.sdk.android.type.SignInOptions
import io.logto.sdk.core.Core
import io.logto.sdk.core.exception.CallbackUriVerificationException
import io.logto.sdk.core.type.CodeTokenResponse
Expand All @@ -17,14 +18,14 @@ class LogtoAuthSession(
val context: Activity,
val logtoConfig: LogtoConfig,
val oidcConfig: OidcConfigResponse,
val redirectUri: String,
val signInOptions: SignInOptions,
private val completion: Completion<LogtoException, CodeTokenResponse>,
) {
private val codeVerifier = GenerateUtils.generateCodeVerifier()
private val state = GenerateUtils.generateState()

fun start() {
if (Uri.parse(redirectUri) == Uri.EMPTY) {
if (Uri.parse(signInOptions.redirectUri) == Uri.EMPTY) {
completion.onComplete(LogtoException(LogtoException.Type.INVALID_REDIRECT_URI), null)
return
}
Expand All @@ -35,12 +36,17 @@ class LogtoAuthSession(
GenerateSignInUriOptions(
authorizationEndpoint = oidcConfig.authorizationEndpoint,
clientId = logtoConfig.appId,
redirectUri = redirectUri,
redirectUri = signInOptions.redirectUri,
codeChallenge = GenerateUtils.generateCodeChallenge(codeVerifier),
state = state,
scopes = logtoConfig.scopes,
resources = logtoConfig.resources,
prompt = logtoConfig.prompt,
prompt = signInOptions.prompt ?: logtoConfig.prompt,
loginHint = signInOptions.loginHint,
firstScreen = signInOptions.firstScreen,
identifiers = signInOptions.identifiers,
extraParams = signInOptions.extraParams,
includeReservedScopes = logtoConfig.includeReservedScopes,
),
)

Expand All @@ -51,7 +57,7 @@ class LogtoAuthSession(
val authorizationCode = try {
CallbackUriUtils.verifyAndParseCodeFromCallbackUri(
callbackUri.toString(),
redirectUri,
signInOptions.redirectUri,
state,
)
} catch (exception: CallbackUriVerificationException) {
Expand All @@ -65,7 +71,7 @@ class LogtoAuthSession(
Core.fetchTokenByAuthorizationCode(
tokenEndpoint = oidcConfig.tokenEndpoint,
clientId = logtoConfig.appId,
redirectUri = redirectUri,
redirectUri = signInOptions.redirectUri,
codeVerifier = codeVerifier,
code = authorizationCode,
resource = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ class LogtoConfig(
resources: List<String>? = null,
val usingPersistStorage: Boolean = true,
val prompt: String = PromptValue.CONSENT,
val includeReservedScopes: Boolean = true,
) {
/**
* Normalize the Logto client configuration per the following rules:
*
* - Add default scopes (`openid`, `offline_access` and `profile`) if not provided.
* - Add default scopes (`openid`, `offline_access` and `profile`) if not provided if includeReservedScopes is true.
* - Add `ReservedResource.Organization` to resources if `UserScope.Organizations` is included in scopes.
*/
val scopes = ScopeUtils.withDefaultScopes(scopes)
val scopes = if (includeReservedScopes) {
ScopeUtils.withDefaultScopes(scopes)
} else {
scopes.orEmpty()
}

val resources = if (this.scopes.contains(UserScope.ORGANIZATIONS)) {
(resources.orEmpty() + ReservedResource.ORGANIZATION)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.logto.sdk.android.type

class SignInOptions(
val redirectUri: String,
val prompt: String? = null,
val firstScreen: String? = null,
val identifiers: List<String>? = null,
val loginHint: String? = null,
val extraParams: Map<String, String>? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.logto.sdk.android.auth.logto

import android.net.Uri
import com.google.common.truth.Truth.assertThat
import io.logto.sdk.android.type.SignInOptions
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
Expand Down Expand Up @@ -66,7 +67,7 @@ class LogtoAuthManagerTest {
mockk(),
mockk(),
mockk(),
redirectUri,
SignInOptions(redirectUri = redirectUri),
mockk()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.google.common.truth.Truth.assertThat
import io.logto.sdk.android.completion.Completion
import io.logto.sdk.android.exception.LogtoException
import io.logto.sdk.android.type.LogtoConfig
import io.logto.sdk.android.type.SignInOptions
import io.logto.sdk.core.Core
import io.logto.sdk.core.exception.CallbackUriVerificationException
import io.logto.sdk.core.http.HttpCompletion
Expand Down Expand Up @@ -45,6 +46,10 @@ class LogtoAuthSessionTest {

private val dummyRedirectUri = "localhost:3001/callback"

private val dummySignInOptions = SignInOptions(
redirectUri = dummyRedirectUri
)

@Before
fun setUp() {
every { mockActivity.packageName } returns "logto.test"
Expand All @@ -67,7 +72,7 @@ class LogtoAuthSessionTest {
mockActivity,
dummyLogtoConfig,
dummyOidcConfigResponse,
dummyRedirectUri,
dummySignInOptions,
mockCompletion
)

Expand Down Expand Up @@ -97,7 +102,7 @@ class LogtoAuthSessionTest {
mockActivity,
mockLogtoConfig,
dummyOidcConfigResponse,
invalidRedirectUri,
SignInOptions(redirectUri = invalidRedirectUri),
mockCompletion,
)

Expand Down Expand Up @@ -131,7 +136,7 @@ class LogtoAuthSessionTest {
mockActivity,
dummyLogtoConfig,
dummyOidcConfigResponse,
dummyRedirectUri,
dummySignInOptions,
mockCompletion,
)

Expand Down Expand Up @@ -174,7 +179,7 @@ class LogtoAuthSessionTest {
mockActivity,
dummyLogtoConfig,
dummyOidcConfigResponse,
dummyRedirectUri,
dummySignInOptions,
mockCompletion,
)

Expand Down Expand Up @@ -231,7 +236,7 @@ class LogtoAuthSessionTest {
mockActivity,
dummyLogtoConfig,
dummyOidcConfigResponse,
dummyRedirectUri,
dummySignInOptions,
mockCompletion,
)

Expand Down Expand Up @@ -267,7 +272,7 @@ class LogtoAuthSessionTest {
mockActivity,
dummyLogtoConfig,
dummyOidcConfigResponse,
dummyRedirectUri,
dummySignInOptions,
mockCompletion,
)

Expand Down

0 comments on commit 4be3174

Please sign in to comment.