-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Iulia Stana
committed
Mar 1, 2023
1 parent
2ccede6
commit dd25e45
Showing
12 changed files
with
639 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"client_id": "dev.egeniq.nl", | ||
"redirect_uri": "http://login.test2.eduid.nl/myconext/api/mobile/swagger-ui/oauth2-redirect.html", | ||
"end_session_redirect_uri": "http://login.test2.eduid.nl", | ||
"authorization_scope": "eduid.nl/mobile", | ||
"discovery_uri": "https://connect.test2.surfconext.nl/oidc/.well-known/openid-configuration", | ||
"authorization_endpoint_uri": "https://connect.test2.surfconext.nl/oidc/authorize", | ||
"token_endpoint_uri": "https://connect.test2.surfconext.nl/oidc/token", | ||
"registration_endpoint_uri": "", | ||
"user_info_endpoint_uri": "", | ||
"https_required": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<resources> | ||
|
||
<string name="app_name">eduID DEBUG</string> | ||
<string name="app_name" translatable="false">eduID DEBUG</string> | ||
|
||
</resources> |
83 changes: 83 additions & 0 deletions
83
app/src/main/kotlin/nl/eduid/di/assist/AuthenticationAssistant.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package nl.eduid.di.assist | ||
|
||
import android.net.Uri | ||
import net.openid.appauth.* | ||
import net.openid.appauth.connectivity.DefaultConnectionBuilder | ||
import nl.eduid.screens.oauth.Configuration | ||
import timber.log.Timber | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
|
||
class AuthenticationAssistant { | ||
|
||
suspend fun retrieveOpenIdDiscoveryDoc(configuration: Configuration): AuthorizationServiceConfiguration = | ||
suspendCoroutine { continuation -> | ||
AuthorizationServiceConfiguration.fetchFromUrl( | ||
configuration.discoveryUri ?: Uri.EMPTY, | ||
{ config: AuthorizationServiceConfiguration?, ex: AuthorizationException? -> | ||
when { | ||
ex != null -> { | ||
Timber.e(ex, "Failed to retrieve discovery document") | ||
continuation.resumeWith(Result.failure(ex)) | ||
} | ||
config != null -> { | ||
continuation.resumeWith(Result.success(config)) | ||
} | ||
else -> { | ||
continuation.resumeWith(Result.failure(RuntimeException("Could not complete discovery"))) | ||
} | ||
} | ||
}, | ||
DefaultConnectionBuilder.INSTANCE | ||
) | ||
} | ||
|
||
suspend fun performRegistrationRequest( | ||
registrationRequest: RegistrationRequest, service: AuthorizationService | ||
): RegistrationResponse = suspendCoroutine { continuation -> | ||
service.performRegistrationRequest( | ||
registrationRequest | ||
) { response: RegistrationResponse?, ex: AuthorizationException? -> | ||
when { | ||
ex != null -> { | ||
Timber.e(ex, "Failed to dynamically register client") | ||
continuation.resumeWith(Result.failure(ex)) | ||
} | ||
response != null -> { | ||
continuation.resumeWith(Result.success(response)) | ||
} | ||
else -> { | ||
continuation.resumeWith(Result.failure(RuntimeException("Could not complete client dynamic registration"))) | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
suspend fun exchangeAuthorizationCode( | ||
response: AuthorizationResponse, | ||
clientAuthentication: ClientAuthentication, | ||
service: AuthorizationService | ||
): TokenResponse = suspendCoroutine { continuation -> | ||
service.performTokenRequest( | ||
/* request = */ | ||
response.createTokenExchangeRequest(), | ||
/* clientAuthentication = */ | ||
clientAuthentication, | ||
) { tokenResponse, ex -> | ||
when { | ||
ex != null -> { | ||
Timber.e(ex, "Failed to exchange authorization code") | ||
continuation.resumeWith(Result.failure(ex)) | ||
} | ||
tokenResponse != null -> { | ||
continuation.resumeWith(Result.success(tokenResponse)) | ||
} | ||
else -> { | ||
continuation.resumeWith(Result.failure(RuntimeException("Could not complete client dynamic registration"))) | ||
} | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
app/src/main/kotlin/nl/eduid/di/repository/StorageRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package nl.eduid.di.repository | ||
|
||
import android.content.Context | ||
import androidx.datastore.preferences.core.edit | ||
import androidx.datastore.preferences.core.emptyPreferences | ||
import androidx.datastore.preferences.core.stringPreferencesKey | ||
import androidx.datastore.preferences.preferencesDataStore | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.catch | ||
import kotlinx.coroutines.flow.map | ||
import net.openid.appauth.AuthState | ||
import net.openid.appauth.AuthorizationRequest | ||
import timber.log.Timber | ||
import java.io.IOException | ||
|
||
class StorageRepository(private val context: Context) { | ||
|
||
private val Context.dataStore by preferencesDataStore( | ||
name = "oauth_settings" | ||
) | ||
|
||
val authState: Flow<AuthState?> = context.dataStore.data.catch { exception -> | ||
if (exception is IOException) { | ||
Timber.e(exception, "Error reading preferences.") | ||
emit(emptyPreferences()) | ||
} else { | ||
throw exception | ||
} | ||
}.map { preferences -> | ||
val authState = preferences[PreferencesKeys.CURRENT_AUTHSTATE] | ||
authState?.let { | ||
AuthState.jsonDeserialize(it) | ||
} | ||
} | ||
|
||
val authRequest: Flow<AuthorizationRequest?> = context.dataStore.data.catch { exception -> | ||
if (exception is IOException) { | ||
Timber.e(exception, "Error reading preferences.") | ||
emit(emptyPreferences()) | ||
} else { | ||
throw exception | ||
} | ||
}.map { preferences -> | ||
val authRequest = preferences[PreferencesKeys.CURRENT_AUTHREQUEST] | ||
authRequest?.let { | ||
AuthorizationRequest.jsonDeserialize(it) | ||
} | ||
} | ||
|
||
val clientId: Flow<String?> = context.dataStore.data.catch { exception -> | ||
if (exception is IOException) { | ||
Timber.e(exception, "Error reading preferences.") | ||
emit(emptyPreferences()) | ||
} else { | ||
throw exception | ||
} | ||
}.map { preferences -> | ||
preferences[PreferencesKeys.CLIENT_ID] | ||
} | ||
|
||
suspend fun saveCurrentAuthState(authState: AuthState?) = context.dataStore.edit { settings -> | ||
settings[PreferencesKeys.CURRENT_AUTHSTATE] = | ||
authState?.jsonSerializeString() ?: settings.remove(PreferencesKeys.CURRENT_AUTHSTATE) | ||
} | ||
|
||
suspend fun saveCurrentAuthRequest(authRequest: AuthorizationRequest?) = | ||
context.dataStore.edit { settings -> | ||
settings[PreferencesKeys.CURRENT_AUTHREQUEST] = authRequest?.jsonSerializeString() | ||
?: settings.remove(PreferencesKeys.CURRENT_AUTHREQUEST) | ||
} | ||
|
||
suspend fun saveClientId(clientId: String) = context.dataStore.edit { settings -> | ||
settings[PreferencesKeys.CLIENT_ID] = clientId | ||
} | ||
|
||
private object PreferencesKeys { | ||
val CURRENT_AUTHSTATE = stringPreferencesKey("current_authstate") | ||
val CURRENT_AUTHREQUEST = stringPreferencesKey("current_authrequest") | ||
val CLIENT_ID = stringPreferencesKey("currentClientId") | ||
} | ||
|
||
} |
32 changes: 32 additions & 0 deletions
32
app/src/main/kotlin/nl/eduid/screens/oauth/Configuration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package nl.eduid.screens.oauth | ||
|
||
import android.net.Uri | ||
|
||
data class Configuration( | ||
val clientId: String?, | ||
val scope: String, | ||
val redirectUri: Uri, | ||
val endSessionRedirectUri: Uri, | ||
val discoveryUri: Uri?, | ||
val authEndpointUri: Uri, | ||
val tokenEndpointUri: Uri, | ||
val endSessionEndpoint: Uri, | ||
val registrationEndpointUri: Uri, | ||
val isHttpsRequired: Boolean | ||
) { | ||
companion object { | ||
val EMPTY = Configuration( | ||
clientId = "", | ||
scope = "", | ||
redirectUri = Uri.EMPTY, | ||
endSessionRedirectUri = Uri.EMPTY, | ||
discoveryUri = Uri.EMPTY, | ||
authEndpointUri = Uri.EMPTY, | ||
tokenEndpointUri = Uri.EMPTY, | ||
endSessionEndpoint = Uri.EMPTY, | ||
registrationEndpointUri = Uri.EMPTY, | ||
isHttpsRequired = true | ||
|
||
) | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
app/src/main/kotlin/nl/eduid/screens/oauth/OAuthContract.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package nl.eduid.screens.oauth | ||
|
||
|
||
import android.content.Context | ||
import android.content.Intent | ||
import androidx.activity.result.contract.ActivityResultContract | ||
import timber.log.Timber | ||
|
||
|
||
class OAuthContract( | ||
) : ActivityResultContract<OAuthViewModel, Intent?>() { | ||
|
||
override fun createIntent(context: Context, viewModel: OAuthViewModel): Intent = try { | ||
viewModel.createAuthorizationIntent() | ||
} catch (e: Exception) { | ||
Timber.e(e, "Failed to create authorization request intent") | ||
Intent() | ||
} | ||
|
||
|
||
override fun parseResult(resultCode: Int, intent: Intent?): Intent? { | ||
return intent | ||
} | ||
} |
Oops, something went wrong.