To run the example project, clone the repo, and run ./gradlew assemble
from the root directory.
You can then install the example APK onto an Android device or emulator.
Add the OktaAppAuth
dependency to your build.gradle
file:
<dependency>
<groupId>com.okta.android</groupId>
<artifactId>appauth-android</artifactId>
<version>0.1.0</version>
<type>pom</type>
</dependency>
compile 'com.okta.android:appauth-android:0.1.0'
<dependency org='com.okta.android' name='appauth-android' rev='0.1.0'>
<artifact name='appauth-android' ext='pom' />
</dependency>
This library currently supports:
You can create an Okta developer account at https://developer.okta.com/.
- After login, from the Admin dashboard, navigate to Applications→Add Application
- Choose Native as the platform
- Populate your new Native OpenID Connect application with values similar to:
Setting | Value |
---|---|
Application Name | Native OpenId Connect App (must be unique) |
Redirect URIs | com.okta.example:/callback |
Allowed grant types | Authorization Code, Refresh Token (recommended) |
- Click Finish to redirect back to the General Settings of your application.
- Copy the Client ID, as it will be needed for the client configuration.
- Get your issuer, which is a combination of your Org URL (found in the upper right of the console home page) and /oauth2/default. For example, https://dev-1234.oktapreview.com/oauth2/default.
Note: As with any Okta application, make sure you assign Users or Groups to the application. Otherwise, no one can use it.
Create a file called okta_app_auth_config.json
in your application's res/raw/
directory with
the following contents:
{
"client_id": "{clientIdValue}",
"redirect_uri": "{redirectUriValue}",
"scopes": [
"openid",
"profile",
"offline_access"
],
"issuer_uri": "https://{yourOktaDomain}.com/oauth2/default"
}
Note: To receive a refresh_token, you must include the offline_access
scope.
In order to redirect back to your application from a web browser, you must specify a unique URI to
your app. To do this, you must define a gradle manifest placeholder in your app's build.gradle
:
android.defaultConfig.manifestPlaceholders = [
"appAuthRedirectScheme": "com.okta.example"
]
Make sure this is consistent with the redirect URI used in okta_app_auth_config.json
. For example,
if your Redirect URI is com.okta.example:/callback
, the AppAuth Redirect Scheme should be
com.okta.example
.
There is a known issue when redirecting back to a URI scheme from the browser via Chrome Custom Tabs. This is due to Chrome not supporting JavaScript initiated redirects back to native applications.
To handle this, the AppAuth team proposes the following:
Create a web page for your redirect URI that displays an interstitial page with a Click here to return to app button. Ian McGinniss (AppAuth-Android Author)
There is a working sample application referenced here, where the interstitial page is used to capture the code
and state
values from the callback, then redirects the user back to the private-use URI scheme specified by the application.
The flow should look similar to:
More information on this topic is recorded in this issue.
First, initialize the Okta AppAuth SDK in the Activity#onCreate
method of the Activity that you
are using to log users into your app. In this example, we will call it LoginActivity
:
// LoginActivity.java
public class LoginActivity extends Activity {
private OktaAppAuth mOktaAuth;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mOktaAuth = OktaAppAuth.getInstance(this);
// Do any of your own setup of the Activity
mOktaAuth.init(
this,
new OktaAppAuth.OktaAuthListener() {
@Override
public void onSuccess() {
// Handle a successful initialization (e.g. display login button)
}
@Override
public void onTokenFailure(@NonNull AuthorizationException ex) {
// Handle a failed initialization
}
});
}
}
Once the OktaAppAuth instance is initialized, you can start the authorization flow by simply calling
login
whenever you're ready:
// LoginActivity.java
public class LoginActivity extends Activity {
private void startAuth() {
Intent completionIntent = new Intent(this, AuthorizedActivity.class);
Intent cancelIntent = new Intent(this, LoginActivity.class);
cancelIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mOktaAuth.login(
this,
PendingIntent.getActivity(this, 0, completionIntent, 0),
PendingIntent.getActivity(this, 0, cancelIntent, 0)
);
}
}
To login using a username hint, simply hookup a LoginHintChangeHandler
to your EditText
that has
the username input. Usually this happens in your onCreate
:
((EditText)findViewById(R.id.login_hint_value)).addTextChangedListener(
new LoginHintChangeHandler(mOktaAuth));
Once a user logs in, you can use the OktaAppAuth object to call the OIDC userInfo endpoint to return user information.
private void fetchUserInfo() {
mOktaAuth.getUserInfo(new OktaAppAuth.OktaAuthActionCallback<JSONObject>() {
@Override
public void onSuccess(JSONObject response) {
// Do whatever you need to do with the user info data
}
@Override
public void onTokenFailure(@NonNull AuthorizationException ex) {
// Handle an error with the Okta authorization and tokens
}
@Override
public void onFailure(int httpResponseCode, Exception ex) {
// Handle a network error when fetching the user info data
}
});
}
In addition to the built in userInfo endpoint, you can use the OktaAppAuth interface to perform
your own authorized requests, whatever they might be. You can use this simple method to make
your own requests and have the access token automatically added to the Authorization
header with
the standard OAuth 2.0 prefix of Bearer
. The performAuthorizedRequest
method will also handle
getting new tokens for you if required:
final URL myUrl; // some protected URL
mOktaAuth.performAuthorizedRequest(new OktaAppAuth.BearerAuthRequest() {
@NonNull
@Override
public HttpURLConnection createRequest() throws Exception {
HttpURLConnection conn = (HttpURLConnection) myUrl.openConnection();
conn.setInstanceFollowRedirects(false); // recommended during authorized calls
return conn;
}
@Override
public void onSuccess(@NonNull InputStream response) {
// Handle successful response in the input stream
}
@Override
public void onTokenFailure(@NonNull AuthorizationException ex) {
// Handle failure to acquire new tokens from Okta
}
@Override
public void onFailure(int httpResponseCode, Exception ex) {
// Handle failure to make your authorized request or a response with a 4xx or
// 5xx HTTP status response code
}
);
You can also refresh the accessToken
if the refreshToken
is provided.
mOktaAuth.refreshAccessToken(new OktaAuth.OktaAuthListener() {
@Override
public void onSuccess() {
// Handle a successful refresh
}
@Override
public void onTokenFailure(@NonNull AuthorizationException ex) {
// Handle a failure to refresh the tokens
}
Tokens are securely stored in the private Shared Preferences.
See the LICENSE file for more info.