Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.applyds:okta-sdk-appauth-android:'
}
dependencies {
implementation("com.github.applyds:okta-sdk-appauth-android:")
}
<dependency>
<groupId>com.github.applyds</groupId>
<artifactId>okta-sdk-appauth-android</artifactId>
<version></version>
</dependency>
libraryDependencies += "com.github.applyds" % "okta-sdk-appauth-android" % ""
:dependencies [[com.github.applyds/okta-sdk-appauth-android ""]]
To run the example project, clone the repo and run ./gradlew assemble
from the root directory.
git clone --recurse-submodules https://github.com/okta/okta-sdk-appauth-android.git
cd okta-sdk-appauth-android
./gradlew assemble
You can then install the example APK onto an Android device or emulator.
Add the OktaAppAuth
dependency to your build.gradle
file:
api 'com.okta.android:appauth-android:0.1.0'
This library currently supports:
You can create an Okta developer account at https://developer.okta.com/.
| Setting | Value | | -------------------- | --------------------------------------------------- | | Application Name | Native OpenId Connect App (must be unique) | | Login URI | com.okta.example:/callback | | End Session URI | com.okta.example:/logoutCallback | | Allowed grant types | Authorization Code, Refresh Token (recommended) |
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}",
"end_session_redirect_uri": "{endSessionUriValue}",
"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
.
ERR_UNKNOWN_URL_SCHEME
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:
<p align="center"> <img src="https://user-images.githubusercontent.com/20212241/38281780-4c3105dc-3761-11e8-81a5-36337b2ab39a.png" width="500px"> </p>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.
In order to perform end session within user's current browser and perform logout
you have to call signOutFromOkta()
whenever you are ready
// LoginActivity.java
public class UserInfoActivity extends Activity {
private void signOutFromOkta() {
Intent completionIntent = new Intent(this, LoginActivity.class);
Intent cancelIntent = new Intent(this, UserInfoActivity.class);
cancelIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mOktaAuth.endSession(
this,
PendingIntent.getActivity(this, 0, completionIntent, 0),
PendingIntent.getActivity(this, 0, cancelIntent, 0)
);
}
}
See the LICENSE file for more info.