Skip to content
This repository has been archived by the owner on Apr 8, 2019. It is now read-only.

Commit

Permalink
Support for revocation of access tokens. Initial support for alternat…
Browse files Browse the repository at this point in the history
…ive (error) flows

Use setArgsLocalized in ApplicationMessages to ensure that arguments are not localized

Fix type-safety issue and make FacebookAccessTokenContext to be Serializable

Use 'email' scope only if configuration scope is null

Some needed fixes for Facebook flow with custom added scope

Handle case when user denied dialog during Facebook OAuth interaction
  • Loading branch information
mposolda committed May 7, 2013
1 parent 6ed8c17 commit 4d198df
Show file tree
Hide file tree
Showing 16 changed files with 410 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class OAuthConstants {

public static final String ERROR_PARAMETER = "error";

public static final String ERROR_ACCESS_DENIED = "access_denied";

// Used in twitter
public static final String OAUTH_VERIFIER = "oauth_verifier";

Expand Down Expand Up @@ -93,7 +95,11 @@ public class OAuthConstants {

public static final String PROFILE_TWITTER_USERNAME = "user.social-info.twitter.userName";

public static final String PROFILE_FACEBOOK_ACCESS_TOKEN = "user.social-info.facebook.accessToken";
// Facebook accessToken could be very long, so we need to split to two attributes
public static final String PROFILE_FACEBOOK_ACCESS_TOKEN_1 = "user.social-info.facebook.accessToken.1";
public static final String PROFILE_FACEBOOK_ACCESS_TOKEN_2 = "user.social-info.facebook.accessToken.2";

public static final String PROFILE_FACEBOOK_SCOPE = "user.social-info.facebook.scope";

public static final String PROFILE_GOOGLE_ACCESS_TOKEN = "user.social-info.google.accessToken";

Expand All @@ -114,7 +120,7 @@ public class OAuthConstants {

public static final String ATTRIBUTE_URL_TO_REDIRECT_AFTER_LINK_SOCIAL_ACCOUNT = "_urlToRedirectAfterLinkSocialAccount";

public static final String ATTRIBUTE_SOCIAL_NETWORK_PROVIDER_TO_UNLINK = "_socialNetworkProviderToUnlink";
public static final String ATTRIBUTE_EXCEPTION_OAUTH = "_oauthException";

public static final String ATTRIBUTE_LINKED_OAUTH_PROVIDER = "_linkedOAuthProviderUsernameAttrName";

Expand All @@ -126,6 +132,8 @@ public class OAuthConstants {

public static final String ATTRIBUTE_VERIFICATION_STATE = "_verificationState";

public static final String ATTRIBUTE_OAUTH_SCOPE = "_oauthScope";

// URL

public static final String FACEBOOK_AUTHENTICATION_URL_PATH = "/facebookAuth";
Expand All @@ -139,6 +147,8 @@ public class OAuthConstants {

public static final String PARAM_OAUTH_INTERACTION = "_oauthInteraction";

public static final String PARAM_CUSTOM_SCOPE = "_oauthCustomScope";

public static final String PARAM_OAUTH_INTERACTION_VALUE_START = "start";


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class OAuthPrincipal<T> implements Principal {
private final OAuthProviderType<T> oauthProviderType;


public OAuthPrincipal(String userName, String firstName, String lastName, String displayName, String email, T accessToken, OAuthProviderType oauthProviderType) {
public OAuthPrincipal(String userName, String firstName, String lastName, String displayName, String email, T accessToken, OAuthProviderType<T> oauthProviderType) {
this.userName = userName;
this.firstName = firstName;
this.lastName = lastName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,12 @@ public enum OAuthExceptionCode {
/**
* Error when revoking of accessToken of any provider failed
*/
EXCEPTION_CODE_TOKEN_REVOKE_FAILED
EXCEPTION_CODE_TOKEN_REVOKE_FAILED,

/**
* Error when OAuth2 flow failed because user denied to permit privileges (scope) for OAuth provider
*/
EXCEPTION_CODE_USER_DENIED_SCOPE;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* JBoss, a division of Red Hat
* Copyright 2013, Red Hat Middleware, LLC, and individual
* contributors as indicated by the @authors tag. See the
* copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.gatein.security.oauth.facebook;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class FacebookAccessTokenContext implements Serializable {

private final String accessToken;
private final Set<String> scopes = new HashSet<String>();

public FacebookAccessTokenContext(String accessToken, String... scopes) {
this.accessToken = accessToken;
for (String scope : scopes) {
this.scopes.add(scope);
}
}

public FacebookAccessTokenContext(String accessToken, String scopesAsString) {
this.accessToken = accessToken;
String[] scopes = scopesAsString.split(",");
for (String scope : scopes) {
this.scopes.add(scope);
}
}

public String getAccessToken() {
return accessToken;
}

public boolean isScopeAvailable(String scope) {
return scopes.contains(scope);
}

public String getScopesAsString() {
Iterator<String> iterator = scopes.iterator();
StringBuilder result;

if (iterator.hasNext()) {
result = new StringBuilder(iterator.next());
} else {
return "";
}

while (iterator.hasNext()) {
result.append("," + iterator.next());
}
return result.toString();
}

public boolean addScope(String scope) {
return scopes.add(scope);
}

@Override
public String toString() {
return new StringBuilder("FacebookAccessTokenContext [")
.append("accessToken=" + accessToken)
.append(", scope=" + getScopesAsString())
.append("]").toString();
}

@Override
public boolean equals(Object that) {
if (that == this) {
return true;
}

if (!(that instanceof FacebookAccessTokenContext)) {
return false;
}

FacebookAccessTokenContext thatt = (FacebookAccessTokenContext)that;
return this.accessToken.equals(thatt.getAccessToken()) && this.scopes.equals(thatt.scopes);
}

@Override
public int hashCode() {
return accessToken.hashCode() * 13 + scopes.hashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ public class FacebookInteractionState {

private final String state;
private final FacebookPrincipal facebookPrincipal;
private final String scope;

public FacebookInteractionState(String state, FacebookPrincipal facebookPrincipal) {
public FacebookInteractionState(String state, FacebookPrincipal facebookPrincipal, String scope) {
this.state = state;
this.facebookPrincipal = facebookPrincipal;
this.scope = scope;
}

public String getState() {
Expand All @@ -45,4 +47,17 @@ public String getState() {
public FacebookPrincipal getFacebookPrincipal() {
return facebookPrincipal;
}

public String getScope() {
return scope;
}

@Override
public String toString() {
return new StringBuilder("FacebookInteractionState[state=")
.append(state)
.append(", principal=" + facebookPrincipal)
.append(", scope=" + scope)
.append("]").toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,20 @@
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface GateInFacebookProcessor extends OAuthProviderProcessor<String> {
public interface GateInFacebookProcessor extends OAuthProviderProcessor<FacebookAccessTokenContext> {

FacebookPrincipal getPrincipal(String accessToken);

FacebookInteractionState processFacebookAuthInteraction(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException;

/**
* Possibility to create new OAuth interaction with custom scope (not just the scope which is provided in configuration)
*
* @param httpRequest
* @param httpResponse
* @param scope custom scope
* @return
* @throws IOException
*/
FacebookInteractionState processFacebookAuthInteraction(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String scope) throws IOException;
}

0 comments on commit 4d198df

Please sign in to comment.