Loading .gitlab-ci.yml +3 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,9 @@ before_script: - echo MURENA_CLIENT_ID=$MURENA_CLIENT_ID >> local.properties - echo MURENA_CLIENT_SECRET=$MURENA_CLIENT_SECRET >> local.properties - echo MURENA_REDIRECT_URI=$MURENA_REDIRECT_URI >> local.properties - echo MURENA_LOGOUT_REDIRECT_URI=$MURENA_LOGOUT_REDIRECT_URI >> local.properties - echo MURENA_BASE_URL=$MURENA_BASE_URL >> local.properties - echo MURENA_DISCOVERY_END_POINT=$MURENA_DISCOVERY_END_POINT >> local.properties - echo GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID >> local.properties - echo GOOGLE_REDIRECT_URI=$GOOGLE_REDIRECT_URI >> local.properties - echo YAHOO_CLIENT_ID=$YAHOO_CLIENT_ID >> local.properties Loading app/build.gradle +7 −2 Original line number Diff line number Diff line Loading @@ -111,6 +111,9 @@ android { buildConfigField "String", "MURENA_CLIENT_ID", "\"${retrieveKey("MURENA_CLIENT_ID")}\"" buildConfigField "String", "MURENA_CLIENT_SECRET", "\"${retrieveKey("MURENA_CLIENT_SECRET")}\"" buildConfigField "String", "MURENA_REDIRECT_URI", "\"${retrieveKey("MURENA_REDIRECT_URI")}\"" buildConfigField "String", "MURENA_LOGOUT_REDIRECT_URI", "\"${retrieveKey("MURENA_LOGOUT_REDIRECT_URI")}\"" buildConfigField "String", "MURENA_BASE_URL", "\"${retrieveKey("MURENA_BASE_URL")}\"" buildConfigField "String", "MURENA_DISCOVERY_END_POINT", "\"${retrieveKey("MURENA_DISCOVERY_END_POINT")}\"" buildConfigField "String", "GOOGLE_CLIENT_ID", "\"${retrieveKey("GOOGLE_CLIENT_ID")}\"" buildConfigField "String", "GOOGLE_REDIRECT_URI", "\"${retrieveKey("GOOGLE_REDIRECT_URI")}\"" Loading @@ -120,7 +123,9 @@ android { manifestPlaceholders = [ 'appAuthRedirectScheme': applicationId, "googleAuthRedirectScheme": retrieveKey("GOOGLE_REDIRECT_URI"), "murenaAuthRedirectScheme": retrieveKey("MURENA_REDIRECT_URI") "murenaAuthRedirectScheme": retrieveKey("MURENA_REDIRECT_URI"), "murenaAuthLogoutRedirectScheme":retrieveKey("MURENA_LOGOUT_REDIRECT_URI") ] } Loading Loading @@ -219,7 +224,7 @@ dependencies { implementation "commons-httpclient:commons-httpclient:3.1@jar" // remove after entire switch to lib v2 implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5' // remove after entire switch to lib v2 implementation 'com.google.code.gson:gson:2.10.1' implementation("foundation.e:Nextcloud-Android-Library:1.0.6-release") { implementation("foundation.e:Nextcloud-Android-Library:1.0.7-u2.17-release") { exclude group: 'com.gitlab.bitfireAT', module: 'dav4jvm' exclude group: 'org.ogce', module: 'xpp3' // unused in Android and brings wrong Junit version exclude group: 'com.squareup.okhttp3' Loading app/src/main/AndroidManifest.xml +12 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <!-- account management permissions not required for own accounts since API level 22 --> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" android:maxSdkVersion="22"/> Loading Loading @@ -682,6 +683,17 @@ </activity> <activity android:name=".ui.signout.OpenIdEndSessionActivity" android:exported="true" > <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="${murenaAuthLogoutRedirectScheme}" /> </intent-filter> </activity> <receiver android:name=".receiver.BootCompletedReceiver" Loading app/src/main/kotlin/at/bitfire/davdroid/authorization/IdentityProvider.kt +51 −26 Original line number Diff line number Diff line Loading @@ -15,8 +15,10 @@ */ package at.bitfire.davdroid.authorization import android.content.Context import android.net.Uri import at.bitfire.davdroid.BuildConfig import at.bitfire.davdroid.R import net.openid.appauth.AuthorizationServiceConfiguration import net.openid.appauth.AuthorizationServiceConfiguration.RetrieveConfigurationCallback Loading @@ -30,40 +32,59 @@ enum class IdentityProvider( clientId: String, clientSecret: String?, redirectUri: String, logoutRedirectUri: String?, scope: String, userInfoEndpoint: String? userInfoEndpoint: String?, baseUrl: String? ) { MURENA( "https://accounts.eeo.one/auth/realms/eeo.one/.well-known/openid-configuration", null, null, BuildConfig.MURENA_CLIENT_ID, BuildConfig.MURENA_CLIENT_SECRET, BuildConfig.MURENA_REDIRECT_URI + ":/redirect", "openid address profile email phone roles offline_access web-origins microprofile-jwt", null discoveryEndpoint = BuildConfig.MURENA_DISCOVERY_END_POINT, authEndpoint = null, tokenEndpoint = null, clientId = BuildConfig.MURENA_CLIENT_ID, clientSecret = BuildConfig.MURENA_CLIENT_SECRET, redirectUri = BuildConfig.MURENA_REDIRECT_URI + ":/redirect", logoutRedirectUri = BuildConfig.MURENA_LOGOUT_REDIRECT_URI + ":/redirect", scope = "openid address profile email phone roles offline_access web-origins microprofile-jwt", userInfoEndpoint = null, baseUrl = BuildConfig.MURENA_BASE_URL, ), GOOGLE( "https://accounts.google.com/.well-known/openid-configuration", null, null, BuildConfig.GOOGLE_CLIENT_ID, null, BuildConfig.GOOGLE_REDIRECT_URI + ":/oauth2redirect", "openid profile email https://www.googleapis.com/auth/carddav https://www.googleapis.com/auth/calendar https://mail.google.com/", null discoveryEndpoint = "https://accounts.google.com/.well-known/openid-configuration", authEndpoint = null, tokenEndpoint = null, clientId = BuildConfig.GOOGLE_CLIENT_ID, clientSecret = null, redirectUri = BuildConfig.GOOGLE_REDIRECT_URI + ":/oauth2redirect", logoutRedirectUri = null, scope = "openid profile email https://www.googleapis.com/auth/carddav https://www.googleapis.com/auth/calendar https://mail.google.com/", userInfoEndpoint = null, baseUrl = null ), YAHOO( "https://api.login.yahoo.com/.well-known/openid-configuration", null, null, BuildConfig.YAHOO_CLIENT_ID, null, BuildConfig.APPLICATION_ID + "://oauth2redirect", "openid openid2 profile email mail-w sdct-w ycal-w", null discoveryEndpoint = "https://api.login.yahoo.com/.well-known/openid-configuration", authEndpoint = null, tokenEndpoint = null, clientId = BuildConfig.YAHOO_CLIENT_ID, clientSecret = null, redirectUri = BuildConfig.APPLICATION_ID + "://oauth2redirect", logoutRedirectUri = null, scope = "openid openid2 profile email mail-w sdct-w ycal-w", userInfoEndpoint = null, baseUrl = null ); companion object { fun retrieveByAccountType(context: Context, accountType: String): IdentityProvider? { return when(accountType) { context.getString(R.string.eelo_account_type) -> MURENA context.getString(R.string.google_account_type) -> GOOGLE context.getString(R.string.yahoo_account_type) -> YAHOO else -> null } } } private val mDiscoveryEndpoint: Uri? private val mAuthEndpoint: Uri? private val mTokenEndpoint: Uri? Loading @@ -71,8 +92,10 @@ enum class IdentityProvider( val clientId: String val clientSecret: String? val redirectUri: Uri val logoutRedirectUri: Uri? val scope: String val userInfoEndpoint: String? val baseUrl: String? init { require( Loading @@ -87,8 +110,10 @@ enum class IdentityProvider( this.clientSecret = clientSecret this.redirectUri = retrieveUri(redirectUri) ?: throw IllegalArgumentException("invalid redirect uri") this.logoutRedirectUri = retrieveUri(logoutRedirectUri) this.scope = scope this.userInfoEndpoint = userInfoEndpoint this.baseUrl = baseUrl } fun retrieveConfig(callback: RetrieveConfigurationCallback) { Loading app/src/main/kotlin/at/bitfire/davdroid/receiver/AccountRemovedReceiver.kt +41 −5 Original line number Diff line number Diff line Loading @@ -20,17 +20,16 @@ import android.accounts.AccountManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountUtils import at.bitfire.davdroid.ui.signout.OpenIdEndSessionActivity import at.bitfire.davdroid.util.AuthStatePrefUtils import com.owncloud.android.lib.common.OwnCloudClientManagerFactory class AccountRemovedReceiver : BroadcastReceiver() { companion object { private const val ACCOUNT_REMOVAL_ACTION = "android.accounts.action.ACCOUNT_REMOVED" } override fun onReceive(context: Context?, intent: Intent?) { if (context == null || intent == null || intent.action != ACCOUNT_REMOVAL_ACTION) { if (context == null || intent == null || intent.action != AccountManager.ACTION_ACCOUNT_REMOVED) { return } Loading @@ -38,6 +37,43 @@ class AccountRemovedReceiver : BroadcastReceiver() { val ownCloudClientManager = OwnCloudClientManagerFactory.getDefaultSingleton() ownCloudClientManager.removeClientForByName(accountName) clearOidcSession( intent = intent, context = context, accountName = accountName ) } private fun clearOidcSession( intent: Intent, context: Context, accountName: String ) { intent.extras?.getString(AccountManager.KEY_ACCOUNT_TYPE)?.let { type -> val authStateString = AuthStatePrefUtils.loadAuthState(context, accountName, type) ?: return startOidcEndSessionActivity( context = context, authState = authStateString, accountType = type ) } } private fun startOidcEndSessionActivity( context: Context, authState: String, accountType: String ) { val intent = Intent(context, OpenIdEndSessionActivity::class.java) intent.apply { putExtra(AccountSettings.KEY_AUTH_STATE, authState) putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountType) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } context.applicationContext.startActivity(intent) } private fun getAccountName(context: Context, intent: Intent): String? { Loading Loading
.gitlab-ci.yml +3 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,9 @@ before_script: - echo MURENA_CLIENT_ID=$MURENA_CLIENT_ID >> local.properties - echo MURENA_CLIENT_SECRET=$MURENA_CLIENT_SECRET >> local.properties - echo MURENA_REDIRECT_URI=$MURENA_REDIRECT_URI >> local.properties - echo MURENA_LOGOUT_REDIRECT_URI=$MURENA_LOGOUT_REDIRECT_URI >> local.properties - echo MURENA_BASE_URL=$MURENA_BASE_URL >> local.properties - echo MURENA_DISCOVERY_END_POINT=$MURENA_DISCOVERY_END_POINT >> local.properties - echo GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID >> local.properties - echo GOOGLE_REDIRECT_URI=$GOOGLE_REDIRECT_URI >> local.properties - echo YAHOO_CLIENT_ID=$YAHOO_CLIENT_ID >> local.properties Loading
app/build.gradle +7 −2 Original line number Diff line number Diff line Loading @@ -111,6 +111,9 @@ android { buildConfigField "String", "MURENA_CLIENT_ID", "\"${retrieveKey("MURENA_CLIENT_ID")}\"" buildConfigField "String", "MURENA_CLIENT_SECRET", "\"${retrieveKey("MURENA_CLIENT_SECRET")}\"" buildConfigField "String", "MURENA_REDIRECT_URI", "\"${retrieveKey("MURENA_REDIRECT_URI")}\"" buildConfigField "String", "MURENA_LOGOUT_REDIRECT_URI", "\"${retrieveKey("MURENA_LOGOUT_REDIRECT_URI")}\"" buildConfigField "String", "MURENA_BASE_URL", "\"${retrieveKey("MURENA_BASE_URL")}\"" buildConfigField "String", "MURENA_DISCOVERY_END_POINT", "\"${retrieveKey("MURENA_DISCOVERY_END_POINT")}\"" buildConfigField "String", "GOOGLE_CLIENT_ID", "\"${retrieveKey("GOOGLE_CLIENT_ID")}\"" buildConfigField "String", "GOOGLE_REDIRECT_URI", "\"${retrieveKey("GOOGLE_REDIRECT_URI")}\"" Loading @@ -120,7 +123,9 @@ android { manifestPlaceholders = [ 'appAuthRedirectScheme': applicationId, "googleAuthRedirectScheme": retrieveKey("GOOGLE_REDIRECT_URI"), "murenaAuthRedirectScheme": retrieveKey("MURENA_REDIRECT_URI") "murenaAuthRedirectScheme": retrieveKey("MURENA_REDIRECT_URI"), "murenaAuthLogoutRedirectScheme":retrieveKey("MURENA_LOGOUT_REDIRECT_URI") ] } Loading Loading @@ -219,7 +224,7 @@ dependencies { implementation "commons-httpclient:commons-httpclient:3.1@jar" // remove after entire switch to lib v2 implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5' // remove after entire switch to lib v2 implementation 'com.google.code.gson:gson:2.10.1' implementation("foundation.e:Nextcloud-Android-Library:1.0.6-release") { implementation("foundation.e:Nextcloud-Android-Library:1.0.7-u2.17-release") { exclude group: 'com.gitlab.bitfireAT', module: 'dav4jvm' exclude group: 'org.ogce', module: 'xpp3' // unused in Android and brings wrong Junit version exclude group: 'com.squareup.okhttp3' Loading
app/src/main/AndroidManifest.xml +12 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <!-- account management permissions not required for own accounts since API level 22 --> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" android:maxSdkVersion="22"/> Loading Loading @@ -682,6 +683,17 @@ </activity> <activity android:name=".ui.signout.OpenIdEndSessionActivity" android:exported="true" > <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="${murenaAuthLogoutRedirectScheme}" /> </intent-filter> </activity> <receiver android:name=".receiver.BootCompletedReceiver" Loading
app/src/main/kotlin/at/bitfire/davdroid/authorization/IdentityProvider.kt +51 −26 Original line number Diff line number Diff line Loading @@ -15,8 +15,10 @@ */ package at.bitfire.davdroid.authorization import android.content.Context import android.net.Uri import at.bitfire.davdroid.BuildConfig import at.bitfire.davdroid.R import net.openid.appauth.AuthorizationServiceConfiguration import net.openid.appauth.AuthorizationServiceConfiguration.RetrieveConfigurationCallback Loading @@ -30,40 +32,59 @@ enum class IdentityProvider( clientId: String, clientSecret: String?, redirectUri: String, logoutRedirectUri: String?, scope: String, userInfoEndpoint: String? userInfoEndpoint: String?, baseUrl: String? ) { MURENA( "https://accounts.eeo.one/auth/realms/eeo.one/.well-known/openid-configuration", null, null, BuildConfig.MURENA_CLIENT_ID, BuildConfig.MURENA_CLIENT_SECRET, BuildConfig.MURENA_REDIRECT_URI + ":/redirect", "openid address profile email phone roles offline_access web-origins microprofile-jwt", null discoveryEndpoint = BuildConfig.MURENA_DISCOVERY_END_POINT, authEndpoint = null, tokenEndpoint = null, clientId = BuildConfig.MURENA_CLIENT_ID, clientSecret = BuildConfig.MURENA_CLIENT_SECRET, redirectUri = BuildConfig.MURENA_REDIRECT_URI + ":/redirect", logoutRedirectUri = BuildConfig.MURENA_LOGOUT_REDIRECT_URI + ":/redirect", scope = "openid address profile email phone roles offline_access web-origins microprofile-jwt", userInfoEndpoint = null, baseUrl = BuildConfig.MURENA_BASE_URL, ), GOOGLE( "https://accounts.google.com/.well-known/openid-configuration", null, null, BuildConfig.GOOGLE_CLIENT_ID, null, BuildConfig.GOOGLE_REDIRECT_URI + ":/oauth2redirect", "openid profile email https://www.googleapis.com/auth/carddav https://www.googleapis.com/auth/calendar https://mail.google.com/", null discoveryEndpoint = "https://accounts.google.com/.well-known/openid-configuration", authEndpoint = null, tokenEndpoint = null, clientId = BuildConfig.GOOGLE_CLIENT_ID, clientSecret = null, redirectUri = BuildConfig.GOOGLE_REDIRECT_URI + ":/oauth2redirect", logoutRedirectUri = null, scope = "openid profile email https://www.googleapis.com/auth/carddav https://www.googleapis.com/auth/calendar https://mail.google.com/", userInfoEndpoint = null, baseUrl = null ), YAHOO( "https://api.login.yahoo.com/.well-known/openid-configuration", null, null, BuildConfig.YAHOO_CLIENT_ID, null, BuildConfig.APPLICATION_ID + "://oauth2redirect", "openid openid2 profile email mail-w sdct-w ycal-w", null discoveryEndpoint = "https://api.login.yahoo.com/.well-known/openid-configuration", authEndpoint = null, tokenEndpoint = null, clientId = BuildConfig.YAHOO_CLIENT_ID, clientSecret = null, redirectUri = BuildConfig.APPLICATION_ID + "://oauth2redirect", logoutRedirectUri = null, scope = "openid openid2 profile email mail-w sdct-w ycal-w", userInfoEndpoint = null, baseUrl = null ); companion object { fun retrieveByAccountType(context: Context, accountType: String): IdentityProvider? { return when(accountType) { context.getString(R.string.eelo_account_type) -> MURENA context.getString(R.string.google_account_type) -> GOOGLE context.getString(R.string.yahoo_account_type) -> YAHOO else -> null } } } private val mDiscoveryEndpoint: Uri? private val mAuthEndpoint: Uri? private val mTokenEndpoint: Uri? Loading @@ -71,8 +92,10 @@ enum class IdentityProvider( val clientId: String val clientSecret: String? val redirectUri: Uri val logoutRedirectUri: Uri? val scope: String val userInfoEndpoint: String? val baseUrl: String? init { require( Loading @@ -87,8 +110,10 @@ enum class IdentityProvider( this.clientSecret = clientSecret this.redirectUri = retrieveUri(redirectUri) ?: throw IllegalArgumentException("invalid redirect uri") this.logoutRedirectUri = retrieveUri(logoutRedirectUri) this.scope = scope this.userInfoEndpoint = userInfoEndpoint this.baseUrl = baseUrl } fun retrieveConfig(callback: RetrieveConfigurationCallback) { Loading
app/src/main/kotlin/at/bitfire/davdroid/receiver/AccountRemovedReceiver.kt +41 −5 Original line number Diff line number Diff line Loading @@ -20,17 +20,16 @@ import android.accounts.AccountManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountUtils import at.bitfire.davdroid.ui.signout.OpenIdEndSessionActivity import at.bitfire.davdroid.util.AuthStatePrefUtils import com.owncloud.android.lib.common.OwnCloudClientManagerFactory class AccountRemovedReceiver : BroadcastReceiver() { companion object { private const val ACCOUNT_REMOVAL_ACTION = "android.accounts.action.ACCOUNT_REMOVED" } override fun onReceive(context: Context?, intent: Intent?) { if (context == null || intent == null || intent.action != ACCOUNT_REMOVAL_ACTION) { if (context == null || intent == null || intent.action != AccountManager.ACTION_ACCOUNT_REMOVED) { return } Loading @@ -38,6 +37,43 @@ class AccountRemovedReceiver : BroadcastReceiver() { val ownCloudClientManager = OwnCloudClientManagerFactory.getDefaultSingleton() ownCloudClientManager.removeClientForByName(accountName) clearOidcSession( intent = intent, context = context, accountName = accountName ) } private fun clearOidcSession( intent: Intent, context: Context, accountName: String ) { intent.extras?.getString(AccountManager.KEY_ACCOUNT_TYPE)?.let { type -> val authStateString = AuthStatePrefUtils.loadAuthState(context, accountName, type) ?: return startOidcEndSessionActivity( context = context, authState = authStateString, accountType = type ) } } private fun startOidcEndSessionActivity( context: Context, authState: String, accountType: String ) { val intent = Intent(context, OpenIdEndSessionActivity::class.java) intent.apply { putExtra(AccountSettings.KEY_AUTH_STATE, authState) putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountType) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } context.applicationContext.startActivity(intent) } private fun getAccountName(context: Context, intent: Intent): String? { Loading