Skip to content
This repository has been archived by the owner on Jan 24, 2025. It is now read-only.

Commit

Permalink
Added in library compatibility for Android API < 20
Browse files Browse the repository at this point in the history
Added ability to provide ConnectionBuilder implementation by client
  • Loading branch information
igormartsekha authored and FeiChen-okta committed Mar 15, 2019
1 parent aa2479b commit 424cff8
Show file tree
Hide file tree
Showing 12 changed files with 400 additions and 19 deletions.
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ You can then install the example APK onto an Android device or emulator.
Add the `OktaAppAuth` dependency to your `build.gradle` file:

```bash
implementation 'com.okta.android:appauth-android:0.2.2'
implementation 'com.okta.android:appauth-android:0.2.3'
```

## Overview
Expand Down Expand Up @@ -195,6 +195,39 @@ private void fetchUserInfo() {
}
```

### Provide Connection Builder

To override network request creating, you can implement `OktaConnnectionBuilder` interface and provide it in `init` method

```java
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
}
},
toolbarColor,
new OktaConnectionBuilder() {
@NonNull
@Override
public HttpURLConnection openConnection(@NonNull Uri uri) throws IOException {
// return HttpURLConnection object
}
});
}
}
```

### Performing Authorized Requests

In addition to the built in userInfo endpoint, you can use the OktaAppAuth interface to perform
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ subprojects {

ext {
versionNum = 2
versionName = "0.2.2"
versionName = "0.2.3"
versionDate = new Date()

// These properties should remain in sync with the values from the AppAuth SDK
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2017, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License,
* Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the
* License.
*/

package com.okta.appauth.android;

import android.net.Uri;
import android.support.annotation.NonNull;

import net.openid.appauth.Preconditions;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.TimeUnit;

/**
* This is ConnectionBuilder which provides to AppAuth library and enable TLS v1.2 for < API 20.
*/
public class DefaultOktaConnectionBuilder implements OktaConnectionBuilder {
/**
* The singleton instance of the Okta default connection builder.
*/
public static final DefaultOktaConnectionBuilder INSTANCE = new DefaultOktaConnectionBuilder();

private static final int CONNECTION_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(15);
private static final int READ_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(10);

private static final String HTTPS_SCHEME = "https";

private DefaultOktaConnectionBuilder() {
// no need to construct instances of this type
}

@NonNull
@Override
public HttpURLConnection openConnection(@NonNull Uri uri) throws IOException {
Preconditions.checkNotNull(uri, "url must not be null");
Preconditions.checkArgument(HTTPS_SCHEME.equals(uri.getScheme()),
"only https connections are permitted");
HttpURLConnection conn = (HttpURLConnection) new URL(uri.toString()).openConnection();
TlsProvider.enableIfNeeded(conn);
conn.setConnectTimeout(CONNECTION_TIMEOUT_MS);
conn.setReadTimeout(READ_TIMEOUT_MS);
conn.setInstanceFollowRedirects(false);
return conn;
}
}
56 changes: 47 additions & 9 deletions library/src/main/java/com/okta/appauth/android/OktaAppAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;

import net.openid.appauth.AppAuthConfiguration;
import net.openid.appauth.AuthState;
import net.openid.appauth.AuthState.AuthStateAction;
Expand All @@ -45,22 +46,25 @@
import net.openid.appauth.EndSessionRequest;
import net.openid.appauth.ResponseTypeValues;
import net.openid.appauth.TokenResponse;
import net.openid.appauth.connectivity.DefaultConnectionBuilder;
import net.openid.appauth.connectivity.ConnectionBuilder;

import okio.Okio;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;



/**
* The SDK's main interaction point with an application. Other operations will stem from this
* class in order to provide a single interface for callers.
Expand Down Expand Up @@ -88,6 +92,8 @@ public class OktaAppAuth {
@ColorInt
protected int mCustomTabColor;

protected ConnectionBuilder mConnectionBuilder;

protected WeakReference<Context> mContext;

/**
Expand Down Expand Up @@ -154,15 +160,44 @@ public void init(
final Context context,
final OktaAuthListener listener,
@ColorInt int customTabColor) {

init(context, listener, customTabColor, DefaultOktaConnectionBuilder.INSTANCE);
}

/**
* Initializes the OktaAppAuth object. This will fetch an OpenID Connect discovery document
* from the issuer in the configuration to configure this instance for use.
*
* @param context The application context
* @param listener An OktaAuthListener that will be called once the initialization is
* complete
* @param customTabColor The color that will be passed to
* {@link CustomTabsIntent.Builder#setToolbarColor(int)}
* @param oktaConnectionBuilder Implementation of {@link OktaConnectionBuilder}
*/
@AnyThread
public void init(
final Context context,
final OktaAuthListener listener,
@ColorInt int customTabColor,
final OktaConnectionBuilder oktaConnectionBuilder) {
mCustomTabColor = customTabColor;
mConnectionBuilder = new ConnectionBuilder() {
@NonNull
@Override
public HttpURLConnection openConnection(@NonNull Uri uri) throws IOException {
return oktaConnectionBuilder.openConnection(uri);
}
};
mExecutor.submit(new Runnable() {
@Override
public void run() {
doInit(context, listener);
doInit(context, mConnectionBuilder, listener);
}
});
}


/**
* Performs revocation of accessToken or refreshToken.
*
Expand Down Expand Up @@ -243,6 +278,7 @@ private void doRevoke(String token,@NonNull RevokeTokenRequest.RevokeListener li
.discoveryDoc.docJson)
.addClientId(mClientId.get())
.addToken(token)
.addConnectionBuilder(mConnectionBuilder)
.build();

request.performRequest(listener);
Expand Down Expand Up @@ -483,9 +519,8 @@ public HttpURLConnection createRequest() throws Exception {
.getAuthorizationServiceConfiguration()
.discoveryDoc;

URL userInfoEndpoint = new URL(discovery.getUserinfoEndpoint().toString());

HttpURLConnection conn = (HttpURLConnection) userInfoEndpoint.openConnection();
HttpURLConnection conn = mConnectionBuilder.openConnection(
discovery.getUserinfoEndpoint());
conn.setInstanceFollowRedirects(false);
return conn;
}
Expand Down Expand Up @@ -602,7 +637,8 @@ public Tokens getTokens() {
}

@WorkerThread
private void doInit(final Context context, final OktaAuthListener listener) {
private void doInit(final Context context, final ConnectionBuilder connectionBuilder,
final OktaAuthListener listener) {
mInitializationListener.set(listener);
recreateAuthorizationService(context);

Expand Down Expand Up @@ -638,7 +674,7 @@ public void onFetchConfigurationCompleted(
handleConfigurationRetrievalResult(serviceConfiguration, ex);
}
},
DefaultConnectionBuilder.INSTANCE);
connectionBuilder);
}

/*
Expand Down Expand Up @@ -758,6 +794,7 @@ AuthorizationService createAuthorizationServiceIfNeeded() {
private AuthorizationService createAuthorizationService(Context context) {
Log.i(TAG, "Creating authorization service");
AppAuthConfiguration.Builder builder = new AppAuthConfiguration.Builder();
builder.setConnectionBuilder(mConnectionBuilder);

return new AuthorizationService(context, builder.build());
}
Expand Down Expand Up @@ -785,7 +822,8 @@ private void doAuth(String sessionToken, OktaNativeAuthListener listener) {
SessionAuthenticationService
sessionAuthenticationService = new SessionAuthenticationService(
mAuthStateManager,
createAuthorizationServiceIfNeeded());
createAuthorizationServiceIfNeeded(),
mConnectionBuilder);
sessionAuthenticationService.performAuthorizationRequest(
mAuthRequest.get(),
sessionToken,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2017, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License,
* Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the
* License.
*/

package com.okta.appauth.android;

import android.net.Uri;
import android.support.annotation.NonNull;

import java.io.IOException;
import java.net.HttpURLConnection;

/**
* Creates {@link java.net.HttpURLConnection} instances for use in direct interactions
* with the authorization service, i.e. those not performed via a browser.
* This interface is similar to Connection Builder in app
* {@link net.openid.appauth.connectivity.ConnectionBuilder}.
* In future net.openid.appauth package will be removed and we don't need to provide any classes
* from this package for client
*/
public interface OktaConnectionBuilder {
/**
* Creates a connection to the specified URL.
* @param uri - Uri
* @throws IOException if an error occurs while attempting to establish the connection.
* @return HttpURLConnection
*/
@NonNull
HttpURLConnection openConnection(@NonNull Uri uri) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
Expand All @@ -34,8 +36,12 @@
import net.openid.appauth.AuthorizationService;
import net.openid.appauth.ClientAuthentication;
import net.openid.appauth.TokenResponse;
import net.openid.appauth.connectivity.ConnectionBuilder;
import net.openid.appauth.internal.Logger;

import java.io.IOException;
import java.net.HttpURLConnection;

/**
* This Activity is used to manage Authorization and end of session requests.
* It will trade the authorization code for the token and notify whether
Expand All @@ -52,6 +58,7 @@ public class OktaManagementActivity extends Activity {

private AuthorizationService mAuthService;
private AuthStateManager mStateManager;
private ConnectionBuilder mConnectionBuilder;

@VisibleForTesting
PendingIntent mCompleteIntent;
Expand Down Expand Up @@ -84,10 +91,18 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mStateManager = AuthStateManager.getInstance(this);
mConnectionBuilder = new ConnectionBuilder() {
@NonNull
@Override
public HttpURLConnection openConnection(@NonNull Uri uri) throws IOException {
return DefaultOktaConnectionBuilder.INSTANCE.openConnection(uri);
}
};

mAuthService = new AuthorizationService(
this,
new AppAuthConfiguration.Builder()
.setConnectionBuilder(mConnectionBuilder)
.build());

if (savedInstanceState == null) {
Expand Down
Loading

0 comments on commit 424cff8

Please sign in to comment.