Skip to content

Commit

Permalink
Merge pull request #29 from Achintha444/main
Browse files Browse the repository at this point in the history
docs: Update docs content of the Android SDK
  • Loading branch information
Achintha444 authored Jun 4, 2024
2 parents 26ed3b6 + 283a5c9 commit 720c3a8
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 15 deletions.
4 changes: 3 additions & 1 deletion docs/website/android/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ This SDK assists you in creating custom login flows directly within the applicat
```groovy
android.defaultConfig.manifestPlaceholders = [
'appAuthRedirectScheme': 'wso2sample' // [!code highlight]
'appAuthRedirectScheme': 'wso2sample',// [!code highlight]
'callbackUriHost': '' // [!code highlight],
'callbackUriScheme': '' // [!code highlight]
]
```
3 changes: 3 additions & 0 deletions docs/website/android/logout.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ If you want to perform a logout, you can call the `logout` function in the <a hr
```kotlin
authenticationProvider.logout(context)
```

> [!NOTE]
> The `logout` function is a suspend function. Therefore, you need to call it inside a coroutine.
36 changes: 25 additions & 11 deletions docs/website/android/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ After that, you can call `authenticationProvider.isLoggedInStateFlow`, this will
```kotlin
@Composable
internal fun LandingScreen() {
val state = authenticationProvider.getAuthenticationStateFlow()
val authenticationStateFlow = authenticationProvider.getAuthenticationStateFlow()

handleAuthenticationState(state)
isLoggedInStateFlow()
handleAuthenticationState(authenticationStateFlow)
}

private fun isLoggedInStateFlow() {
Expand All @@ -74,7 +74,7 @@ private fun isLoggedInStateFlow() {
}
}

private fun handleAuthenticationState(state: AuthenticationState) {
private fun handleAuthenticationState(authenticationStateFlow: SharedFlow<AuthenticationState>) {
GlobalScope.launch {
state.collect {
when (it) {
Expand All @@ -101,6 +101,7 @@ private fun handleAuthenticationState(state: AuthenticationState) {
* Gets called when /authn responds with an “SUCCESS” state. This means
* authentication flow is completed
*/

onSuccessfulLogin()
}
is AuthenticationState.Loading -> {
Expand All @@ -112,6 +113,9 @@ private fun handleAuthenticationState(state: AuthenticationState) {
}
```

> [!NOTE]
> You cannot directly use Composable functions inside a coroutine, above its used to show the flow of the application. The best approach you can take is to use [navigation](https://developer.android.com/guide/navigation).
Assuming that you have configured Username and Password as the first authentication step and TOTP as the second step, you can develop the UI as follows using the <a href="/mobile-ui-sdks/android/api/core-auth-direct/io.asgardeo.android.core_auth_direct.models.autheniticator/-authenticator-types/index.html" target="_blank">AuthenticatorTypes</a> provided by the SDK to populate the login form.
```kotlin
/**
Expand All @@ -125,11 +129,11 @@ internal fun LoginForm(
authenticationFlow.nextStep.authenticators.forEach {
when (it.authenticator) {
AuthenticatorTypes.BASIC_AUTHENTICATOR.authenticatorType -> { // [!code highlight]
BasicAuth(authenticatorType = it)
BasicAuth(authenticator = it)
}

AuthenticatorTypes.TOTP_AUTHENTICATOR.authenticatorType -> { // [!code highlight]
TotpAuth(authenticatorType = it)
TotpAuth(authenticator = it)
}
}
}
Expand All @@ -142,10 +146,14 @@ In the BasicAuth component you can call the authentication function provided by
internal fun BasicAuth(authenticator: Authenticator) {
BasicAuthComponent(
onLoginClick = { username, password ->
authenticationProvider.authenticateWithUsernameAndPassword( // [!code highlight]
username = username,
password = password
)
GlobalScope.launch {
authenticationProvider.authenticateWithUsernameAndPassword(
context = context,
authenticatorId = authenticator.authenticatorId,
username = username,
password = password
)
}
}
)
}
Expand All @@ -157,15 +165,16 @@ fun BasicAuthComponent(
Column() {
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }

OutlinedTextField(
value = username,
onValueChange = { username = it },
label = "Username"
label = { Text(text = "Username") }
)
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = "Password"
label = { Text(text = "Password") }
)
Button(onClick = { onLoginClick(username, password) }) {
Text(text = "Login")
Expand All @@ -175,3 +184,8 @@ fun BasicAuthComponent(
```

You will not need to handle the authentication state in multiple places, you can do it at the start of the application, and it will handle the state accordingly.

> [!CAUTION]
> When using `GlobalScope`, make sure to cancel the coroutine when the composable is removed from the screen. This is to avoid memory leaks.
> Also instead of using `GlobalScope`, you can use `viewModelScope` if you are using the MVVM pattern in your application.
> For more information on how to handle coroutines in Jetpack Compose, see [the following documentation](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/).
3 changes: 3 additions & 0 deletions docs/website/android/token-information.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ tokenProvider.performAction(context) { accessToken, idToken, ->
action(accessToken, idToken)
}
```

> [!NOTE]
> All the functions mentioned above are suspend functions. Therefore, you need to call them inside a coroutine.
2 changes: 1 addition & 1 deletion docs/website/android/use-authenticators.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,6 @@ authenticationProvider.authenticateWithMicrosoftRedirect(
```kotlin
authenticationProvider.authenticateWithOpenIdConnect(
context,
authenticatorId = authenticator.authenticatorId
authenticatorId = authenticator.authenticatorId
)
```
12 changes: 10 additions & 2 deletions docs/website/android/user-details.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,21 @@
After the user is authenticated, to get user-related information, we can use the following function. This will return the user details in a `LinkedHashMap`.

```kotlin
coroutineScope.launch {
GlobalScope.launch {
runCatching {
authenticationProvider.getUserDetails(<context>) // [!code highlight]
authenticationProvider.getBasicUserInfo(<context>) // [!code highlight]
}.onSuccess { userDetails ->
Profile(userDetails)
}.onFailure { e ->
// Display error message
}
}
```

> [!NOTE]
> You cannot directly use Composable functions inside a coroutine, above its used to show the flow of the application. You can use the `getBasicUserInfo` function in a ViewModel or a Repository and observe the result in the Composable function.
> [!CAUTION]
> When using `GlobalScope`, make sure to cancel the coroutine when the composable is removed from the screen. This is to avoid memory leaks.
> Also instead of using `GlobalScope`, you can use `viewModelScope` if you are using the MVVM pattern in your application.
> For more information on how to handle coroutines in Jetpack Compose, see [the following documentation](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/).

0 comments on commit 720c3a8

Please sign in to comment.