Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Added OIDCLibrary to the project
Browse files Browse the repository at this point in the history
  • Loading branch information
ricalo committed Oct 10, 2016
1 parent be59bf4 commit a5ea4b4
Show file tree
Hide file tree
Showing 49 changed files with 3,568 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Expand Up @@ -28,6 +28,7 @@ dependencies {

// Azure Active Directory Library
compile 'com.microsoft.aad:adal:1.2.0'
compile project(':oidclib')

// Retrofit + custom HTTP
compile 'com.squareup.okhttp3:okhttp:3.3.1'
Expand Down
1 change: 1 addition & 0 deletions oidclib/.gitignore
@@ -0,0 +1 @@
/build
60 changes: 60 additions & 0 deletions oidclib/build.gradle
@@ -0,0 +1,60 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 23
buildToolsVersion '23.0.2'

defaultConfig {
minSdkVersion 9
targetSdkVersion 23
versionCode 2
versionName "1.1"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// For backwards compatibility, not necessarily needed
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'

// Google's OAuth library for OpenID Connect
// See https://code.google.com/p/google-oauth-java-client/wiki/Setup
compile('com.google.oauth-client:google-oauth-client:1.21.0') {
exclude group: 'com.google.http-client', module: 'google-http-client'
exclude group: 'com.google.code.findbugs', module: 'jsr305'
exclude group: 'com.google.http-client', module: 'google-http-client-jackson'
exclude group: 'junit', module: 'junit'
exclude group: 'com.google.guava', module: 'guava-jdk5'
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
}
// Google's JSON parsing, could be replaced with Jackson
compile('com.google.api-client:google-api-client-gson:1.21.0') {
exclude group: 'com.google.api-client', module: 'google-api-client'
exclude group: 'com.google.code.findbugs', module: 'jsr305'
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
}
// For backwards compatibility, not necessarily needed
compile('com.google.api-client:google-api-client-android:1.21.0') {
exclude group: 'com.google.android', module: 'android'
exclude group: 'com.google.code.findbugs', module: 'jsr305'
exclude group: 'com.google.guava', module: 'guava-jdk5'
exclude group: 'junit', module: 'junit'
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
exclude group: 'com.google.http-client', module: 'google-http-client-jackson2'
}

// Easier HTTP requests, not necessarily needed
compile('com.github.kevinsawicki:http-request:6.0') {
exclude group: 'junit', module: 'junit'
}

// Encryption for Pre Loli devices
compile 'com.madgag.spongycastle:core:1.54.0.0'
}
43 changes: 43 additions & 0 deletions oidclib/proguard-rules.pro
@@ -0,0 +1,43 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}

# Needed to keep generic types and @Key annotations accessed via reflection
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
-keepclassmembers class * {
@com.google.api.client.util.Key <fields>;
}

# Needed by google-http-client-android when linking against an older platform version
-dontwarn com.google.api.client.extensions.android.**

# Needed by google-api-client-android when linking against an older platform version
-dontwarn com.google.api.client.googleapis.extensions.android.**

# Needed by google-play-services when linking against an older platform version
-dontwarn com.google.android.gms.**
-dontnote com.google.android.gms.**

# com.google.client.util.IOUtils references java.nio.file.Files when on Java 7+
-dontnote java.nio.file.Files, java.nio.file.Path

# Suppress notes on LicensingServices
-dontnote **.ILicensingService

# Suppress warnings on sun.misc.Unsafe
-dontnote sun.misc.Unsafe
-dontwarn sun.misc.Unsafe
@@ -0,0 +1,13 @@
package com.lnikkila.oidc;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
13 changes: 13 additions & 0 deletions oidclib/src/main/AndroidManifest.xml
@@ -0,0 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lnikkila.oidc">

<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />

<application
android:allowBackup="true"
android:label="@string/app_name">
</application>

</manifest>
Binary file added oidclib/src/main/assets/Roboto-BoldCondensed.ttf
Binary file not shown.
196 changes: 196 additions & 0 deletions oidclib/src/main/java/com/lnikkila/oidc/OIDCAccountManager.java
@@ -0,0 +1,196 @@
package com.lnikkila.oidc;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.auth.openidconnect.IdTokenResponse;
import com.google.api.client.util.Preconditions;
import com.lnikkila.oidc.authenticator.Authenticator;
import com.lnikkila.oidc.security.AccountSensitiveDataStorageUtils;
import com.lnikkila.oidc.security.UserNotAuthenticatedWrapperException;

import java.io.IOException;

/**
* A layer of syntactic sugar around the AccountManager and the Accounts.
* @author Camilo Montes
* @since 20/01/2016.
*/
public class OIDCAccountManager {

private final String TAG = getClass().getSimpleName();

private final Context context;
private final AccountManager manager;
private final AccountSensitiveDataStorageUtils secureStorage;


public OIDCAccountManager(Context context) {
this.context = Preconditions.checkNotNull(context);
this.manager = AccountManager.get(this.context);
this.secureStorage = new AccountSensitiveDataStorageUtils(context);
}

public AccountManager getAccountManager() {
return this.manager;
}

public String getAccountType() {
return context.getString(R.string.account_authenticator_type);
}

public Account[] getAccounts() {
return this.manager.getAccountsByType(getAccountType());
}

public Account getAccountByName(String accountName) {
if(accountName != null) {
Account[] accounts = this.getAccounts();
for (Account account : accounts) {
if (accountName.equals(account.name)) {
return account;
}
}
}
return null;
}

public void createAccount(Activity activity, AccountManagerCallback<Bundle> callback) {
this.manager.addAccount(getAccountType(), Authenticator.TOKEN_TYPE_ID, null, null, activity, callback, null);
}

public boolean removeAccount(String accountName) {
Account account = getAccountByName(accountName);
return removeAccount(account);
}

public boolean removeAccount(Account account) {
boolean removed = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){
removed = this.manager.removeAccountExplicitly(account);
}
else {
@SuppressWarnings("deprecation") AccountManagerFuture<Boolean> futureRemoved = this.manager.removeAccount(account, null, null);
try {
removed = futureRemoved.getResult();
} catch (OperationCanceledException | IOException | AuthenticatorException e) {
Log.w("LogoutTask", "Coudln't remove account using pre LOLIPOP remove call");
}
}
return removed;
}

public boolean isKeyPinRequired() {
boolean keyPinRequired = false;
if (context != null) {
keyPinRequired = context.getResources().getBoolean(R.bool.oidc_encryptKeyAskPin);
}
return keyPinRequired;
}

public void invalidateAllAccountTokens(Account account) {
if(account != null) {
try {
String idToken = getIdToken(account.name, null);
String accessToken = getAccessToken(account.name, null);
String refreshToken = getRefreshToken(account.name, null);
this.secureStorage.invalidateStringData(this.manager, account, idToken);
this.secureStorage.invalidateStringData(this.manager, account, accessToken);
this.secureStorage.invalidateStringData(this.manager, account, refreshToken);
} catch (AuthenticatorException | UserNotAuthenticatedWrapperException | OperationCanceledException | IOException e) {
Log.w(TAG, String.format("Could not invalidate account %1$s tokens", account.name), e);
}
}
}

public void invalidateAuthTokens(Account account) {
if(account != null) {
try {
String idToken = getIdToken(account.name, null);
String accessToken = getAccessToken(account.name, null);
this.secureStorage.invalidateStringData(this.manager, account, idToken);
this.secureStorage.invalidateStringData(this.manager, account, accessToken);
} catch (AuthenticatorException | UserNotAuthenticatedWrapperException | OperationCanceledException | IOException e) {
Log.w(TAG, String.format("Could not invalidate account %1$s tokens", account.name), e);
}
}
}


public void invalidateAccessToken(Account account) {
if(account != null) {
try {
String accessToken = getAccessToken(account, null);
this.secureStorage.invalidateStringData(this.manager, account, accessToken);
} catch (AuthenticatorException | UserNotAuthenticatedWrapperException | OperationCanceledException | IOException e) {
Log.w(TAG, String.format("Could not invalidate account %1$s AT", account.name), e);
}
}
}

public String getIdToken(String accountName, AccountManagerCallback<Bundle> callback)
throws AuthenticatorException, UserNotAuthenticatedWrapperException, OperationCanceledException, IOException {
return getToken(accountName, Authenticator.TOKEN_TYPE_ID, callback);
}

public String getAccessToken(Account account, AccountManagerCallback<Bundle> callback)
throws AuthenticatorException, UserNotAuthenticatedWrapperException, OperationCanceledException, IOException {
return getToken(account, Authenticator.TOKEN_TYPE_ACCESS, callback);
}

public String getAccessToken(String accountName, AccountManagerCallback<Bundle> callback)
throws AuthenticatorException, UserNotAuthenticatedWrapperException, OperationCanceledException, IOException {
return getToken(accountName, Authenticator.TOKEN_TYPE_ACCESS, callback);
}

public String getRefreshToken(String accountName, AccountManagerCallback<Bundle> callback)
throws AuthenticatorException, UserNotAuthenticatedWrapperException, OperationCanceledException, IOException {
return getToken(accountName, Authenticator.TOKEN_TYPE_REFRESH, callback);
}

private String getToken(String accountName, String tokenType, AccountManagerCallback<Bundle> callback)
throws AuthenticatorException, UserNotAuthenticatedWrapperException, OperationCanceledException, IOException {
Account account = getAccountByName(accountName);
return getToken(account, tokenType, callback);
}

private String getToken(Account account, String tokenType, AccountManagerCallback<Bundle> callback)
throws AuthenticatorException, UserNotAuthenticatedWrapperException, OperationCanceledException, IOException {
return this.secureStorage.retrieveStringData(this.manager, account, tokenType, callback);
}

public void saveTokens(Account account, TokenResponse tokenResponse) throws UserNotAuthenticatedWrapperException {
if (tokenResponse instanceof IdTokenResponse) {
saveToken(account, Authenticator.TOKEN_TYPE_ID, ((IdTokenResponse) tokenResponse).getIdToken());
}
saveToken(account, Authenticator.TOKEN_TYPE_ACCESS, tokenResponse.getAccessToken());
saveToken(account, Authenticator.TOKEN_TYPE_REFRESH, tokenResponse.getRefreshToken());
}

public void saveTokens(String accountName, TokenResponse tokenResponse) throws UserNotAuthenticatedWrapperException {
if (tokenResponse instanceof IdTokenResponse) {
saveToken(accountName, Authenticator.TOKEN_TYPE_ID, ((IdTokenResponse)tokenResponse).getIdToken());
}
saveToken(accountName, Authenticator.TOKEN_TYPE_ACCESS, tokenResponse.getAccessToken());
saveToken(accountName, Authenticator.TOKEN_TYPE_REFRESH, tokenResponse.getRefreshToken());
}

private void saveToken(String accountName, String tokenType, String token) throws UserNotAuthenticatedWrapperException {
Account account = getAccountByName(accountName);
saveToken(account, tokenType, token);
}

private void saveToken(Account account, String tokenType, String token) throws UserNotAuthenticatedWrapperException {
this.secureStorage.storeStringData(this.manager, account, tokenType, token);
}
}

0 comments on commit a5ea4b4

Please sign in to comment.