Android OpenId Connect library that can be used with any OIDC provider for easy to use authentication. We value developer time and effort, so we developed a dead simple zero config library that any one could easily integrate in a minute, while allowing veterans of authentication to customize everything to their needs.
- Requirements
- Installation
- OIDC Provider Configuration
- Configuration
- Login
- Logout
- Using the Tokens
- Advanced Usage
- Example App
- Acknowledgements
- License
PlusAuth OpenID Connect Library for Android supports Android Apis starting from 16(Jelly Bean) and above.
Add the library dependency to your build.gradle
file:
implementation 'com.plusauth:android:0.1.10'
This library uses and requires Java 8 support. Check out Android Documentation to learn more.
To enable, add the following following to your build.gradle
file
android {
...
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// For Kotlin projects
kotlinOptions {
jvmTarget = "1.8"
}
}
To use the library you must have a OIDC provider account. In this part we will use PlusAuth as an example.
- Create a Plusauth account and a tenant at PlusAuth Dashboard
- Navigate to
Clients
tab and create a client of typeNative Application
. - Go to details page of the client that you've just created and set the following fields as:
- Redirect Uris:
${your-application-id}:/callback
- Post Logout Redirect Uris:
${your-application-id}:/callback
Done! Note your 'Client Id' and 'domain' for library configuration later.
The entry point of the library is the OIDC object. OIDC object can be created by using the OIDCBuilder.
OIDC oidc = new OIDCBuilder(
context,
"your-client-id",
"your-oidc-domain")
.build();
By default library uses Authorization Code + PKCE flow for maximum security. Library wraps all steps of auth flow in to a single call:
oidc.login(context, new LoginRequest(), new AuthenticationCallback() {
@Override
public void onSuccess(Credentials credentials) {
runOnUiThread(()->{
// do ui related work
});
}
@Override
public void onFailure(AuthenticationException e) {
Log.e("TAG", "Login failed", e);
}
});
OIDC will open a browser custom tab(if supported) or browser page showing them your OIDC login page and users will be returned back to the app after they complete the login.
After successful response credentials will be locally stored to skip the OIDC flow at next login. If there are valid credentials in Storage they will be returned instead, skipping OIDC exchange.
This call is asychronous and requires a callback. If you want to do ui related work in callback you must use Activity.runOnUiThread to switch back to main thread since login request is executed in a seperate thread.
Logout call is similar to login:
oidc.logout(this, new LogoutRequest(), new VoidCallback() {
@Override
public void onSuccess(Void aVoid) {
runOnUiThread(()->{
// do ui related work
});
}
@Override
public void onFailure(AuthenticationException e) {
Log.e("TAG", "Logout failed", e);
});
OIDC will momenrarily open a browser custom tab(if supported) or page of OIDC logout page and users will be immediately returned back to the app. This clears users browser session.
After successful response credentials will be locally removed. This completes the two step logout process. If there aren't valid credentials in Storage request will fail.
If you have them, you can revoke your refresh tokens using the Revoke tokens method from Api.
This call is asychronous and requires a callback. If you want to do ui related work in callback you must use Activity.runOnUiThread to switch back to main thread since login request is executed in a seperate thread.
Api class wraps common OIDC calls and provides easy to use interface. Requests can be called both asynchronously or synchronously. No arg method overloads uses provided storage instance to get required tokens.
Obtain api instance:
Api api = oidc.getApi();
If you create the api instance manually, make sure to set credentials manager so the no arg overloads can be used, otherwise you will get null pointer errors(also could occur if storage does not have credentials).
Get User Profile information using /userinfo endpoint:
api.userInfo().call(new PACallback<UserProfile, AuthenticationException>() {
@Override
public void onSuccess(UserProfile userProfile) {
runOnUiThread(() -> {
// do ui related work
});
}
@Override
public void onFailure(AuthenticationException e) {
Log.e("TAG", "Could not get profile", e);
}
});
Sends auth token to /token endpoint of the provider in exchange for credentials.
api.token("your-auth-token").call(new AuthenticationCallback() {
@Override
public void onSuccess(Credentials credentials) {
runOnUiThread(() -> {
// do ui related work
});
}
@Override
public void onFailure(AuthenticationException e) {
Log.e("TAG", "Could exchange auth token", e);
}
});
Renew your credentials using a refresh token. Note that 'offline_access' scope is required to get a refresh refresh token at login, which is added by default.
api.renewAuth().call(new AuthenticationCallback() {
@Override
public void onSuccess(Credentials credentials) {
runOnUiThread(() -> {
// do ui related work
});
}
@Override
public void onFailure(AuthenticationException e) {
Log.e("TAG", "Could not renew auth", e);
}
});
Revoke a token using the revokeToken method. No arg overload only revokes the stored refresh token:
api.revokeToken().call(new VoidCallback() {
@Override
public void onSuccess(Void aVoid) {
runOnUiThread(() -> {
// do ui related work
});
}
@Override
public void onFailure(AuthenticationException e) {
Log.e("TAG", "Could not revoke token", e);
}
});
By default library uses SharedPreferences in Private mode(can only be accessed by this application) for persistence. You are free to implement the Storage interface with your preferred storage backend.
Configure your Storage:
OIDC oidc = new OIDCBuilder(
context,
"your-client-id",
"your-oidc-domain")
.setStorage(new Storage() {
@Override
public void write(@NonNull String s, @Nullable String s1) {
}
@Override
public void delete(@NonNull String s) {
}
@Override
public String read(@NonNull String s) {
return null;
}
})
.build();
By default library does not use any encryption when storing credentials. You are free to implement the Encryptor interface with your preferred encryption method. We provide AESEncryptor class for 256 bit AES GCM implementation which can be used from Android Api 23 and up.
Configure your Encryptor:
OIDC oidc = new OIDCBuilder(
context,
"your-client-id",
"your-oidc-domain")
.setEncryptor(new Encryptor() {
@Override
public String encrypt(String s) {
return null;
}
@Override
public String decrypt(String s) {
return null;
}
})
.build();
We built a very simple app demonstrating login/logout and fetching user info. Check it out here.
Design of this library was inspired by awesome OSS libraries such as AppAuth.
If you have used OIDC with any Android library, you might have felt overwhelmed. We did too. That is why we built PlusAuth OIDC Library For Android. We hope to lower the entry barrier for OIDC complexity so that all developers could enjoy benefits that it brings.
This project is licensed under the MIT license. See the LICENSE file for more info.