Skip to content

Bearer Authentication #988

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 39 additions & 7 deletions library/src/main/java/com/loopj/android/http/AsyncHttpClient.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package com.loopj.android.http;

/*
Android Asynchronous Http Client
Copyright (c) 2011 James Smith <james@loopj.com>
https://loopj.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://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.loopj.android.http;

import android.content.Context;
import android.media.session.MediaSession;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see MediaSession used anywhere else than in this import

import android.os.Looper;

import java.io.IOException;
Expand Down Expand Up @@ -50,6 +48,7 @@
import cz.msebera.android.httpclient.HttpResponse;
import cz.msebera.android.httpclient.HttpResponseInterceptor;
import cz.msebera.android.httpclient.HttpVersion;
import cz.msebera.android.httpclient.auth.AuthSchemeRegistry;
import cz.msebera.android.httpclient.auth.AuthScope;
import cz.msebera.android.httpclient.auth.AuthState;
import cz.msebera.android.httpclient.auth.Credentials;
Expand All @@ -76,6 +75,7 @@
import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory;
import cz.msebera.android.httpclient.entity.HttpEntityWrapper;
import cz.msebera.android.httpclient.impl.auth.BasicScheme;
import cz.msebera.android.httpclient.impl.client.BasicCredentialsProvider;
import cz.msebera.android.httpclient.impl.client.DefaultHttpClient;
import cz.msebera.android.httpclient.impl.conn.tsccm.ThreadSafeClientConnManager;
import cz.msebera.android.httpclient.params.BasicHttpParams;
Expand Down Expand Up @@ -251,6 +251,11 @@ public void process(HttpResponse response, HttpContext context) {
httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
@Override
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {

AuthSchemeRegistry authSchemeRegistry = new AuthSchemeRegistry();
authSchemeRegistry.register("Bearer", new BearerAuthSchemeFactory());
context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, authSchemeRegistry);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this line, it means we're overriding any AUTHSCHEME_REGISTRY already contained by underlying HttpContext ? This should be enabled on-demand, not as only AuthScheme available from library


AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
ClientContext.CREDS_PROVIDER);
Expand All @@ -259,7 +264,11 @@ public void process(final HttpRequest request, final HttpContext context) throws
if (authState.getAuthScheme() == null) {
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if (creds != null) {
if(creds instanceof TokenCredentials) {
authState.setAuthScheme(new BearerAuthSchemeFactory.BearerAuthScheme());
authState.setCredentials(creds);
}
else if (creds != null) {
authState.setAuthScheme(new BasicScheme());
authState.setCredentials(creds);
}
Expand Down Expand Up @@ -791,6 +800,29 @@ public void removeHeader(String header) {
clientHeaderMap.remove(header);
}

/**
* Sets bearer authentication for the request. Uses AuthScope.ANY. This is the same as
* setBearerAuth('token',AuthScope.ANY, false)
* @param token Bearer Token
*/
public void setBearerAuth(String token) {
setBearerAuth(token, AuthScope.ANY, false);
}


/**
* Sets bearer authentication for the request. You should pass in your AuthScope for security. It
* should be like this setBearerAuth("token", new AuthScope("host",port,AuthScope.ANY_REALM), false)
* @param token Bearer Token
* @param scope an AuthScope object
* @param preemptive sets authorization in preemptive manner
*/
public void setBearerAuth(String token, AuthScope scope, boolean preemptive) {
TokenCredentials credentials = new TokenCredentials(token);
setCredentials(scope, credentials);
setAuthenticationPreemptive(preemptive);
}

/**
* Sets basic authentication for the request. Uses AuthScope.ANY. This is the same as
* setBasicAuth('username','password',AuthScope.ANY)
Expand Down Expand Up @@ -1635,4 +1667,4 @@ public void consumeContent() throws IOException {
super.consumeContent();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.loopj.android.http;

import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpRequest;
import cz.msebera.android.httpclient.auth.AUTH;
import cz.msebera.android.httpclient.auth.AuthScheme;
import cz.msebera.android.httpclient.auth.AuthSchemeFactory;
import cz.msebera.android.httpclient.auth.AuthenticationException;
import cz.msebera.android.httpclient.auth.ContextAwareAuthScheme;
import cz.msebera.android.httpclient.auth.Credentials;
import cz.msebera.android.httpclient.auth.MalformedChallengeException;
import cz.msebera.android.httpclient.message.BufferedHeader;
import cz.msebera.android.httpclient.params.HttpParams;
import cz.msebera.android.httpclient.protocol.HttpContext;
import cz.msebera.android.httpclient.util.CharArrayBuffer;

/**
* Created by chase on 08/10/2015.
*/
public class BearerAuthSchemeFactory implements AuthSchemeFactory {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add proper copyright claim here


@Override
public AuthScheme newInstance(HttpParams params) {
return new BearerAuthScheme();
}

public static class BearerAuthScheme implements ContextAwareAuthScheme {
private boolean complete = false;

@Override
public void processChallenge(Header header) throws MalformedChallengeException {
this.complete = true;
}

@Override
public Header authenticate(Credentials credentials, HttpRequest request) throws AuthenticationException {
return authenticate(credentials, request, null);
}

@Override
public Header authenticate(Credentials credentials, HttpRequest request, HttpContext httpContext)
throws AuthenticationException {
CharArrayBuffer buffer = new CharArrayBuffer(32);
buffer.append(AUTH.WWW_AUTH_RESP);
buffer.append(": Bearer ");
buffer.append(credentials.getUserPrincipal().getName());
return new BufferedHeader(buffer);
}

@Override
public String getSchemeName() {
return "Bearer";
}

@Override
public String getParameter(String name) {
return null;
}

@Override
public String getRealm() {
return null;
}

@Override
public boolean isConnectionBased() {
return false;
}

@Override
public boolean isComplete() {
return this.complete;
}
}
}
28 changes: 28 additions & 0 deletions library/src/main/java/com/loopj/android/http/TokenCredentials.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.loopj.android.http;

/**
* Created by chase on 08/10/2015.
*/
import java.security.Principal;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add correct copyright


import cz.msebera.android.httpclient.auth.BasicUserPrincipal;
import cz.msebera.android.httpclient.auth.Credentials;

public class TokenCredentials implements Credentials {
private Principal userPrincipal;

public TokenCredentials(String token) {
this.userPrincipal = new BasicUserPrincipal(token);
}

@Override
public Principal getUserPrincipal() {
return userPrincipal;
}

@Override
public String getPassword() {
return null;
}

}