Skip to content

Commit

Permalink
unit testing oauth token endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
barmintor committed Jul 15, 2013
1 parent a77524c commit b8be39c
Show file tree
Hide file tree
Showing 17 changed files with 1,426 additions and 120 deletions.
Expand Up @@ -86,11 +86,4 @@ public OAuthDecision validateRequest(final String rsId, final String token,
return null;
}

/**
* Test wiring, so w e can set the sessionFactory field without spring
* @param sessionFactory
*/
public void setSessionFactory(final SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
@@ -0,0 +1,58 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* 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
*
* 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 org.fcrepo.auth.oauth;

import javax.jcr.RepositoryException;

import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;


public interface TokenRequestValidations {
/**
* Checks the validity of the auth code attached to the given request
* @param oauthRequest
* @return
* @throws RepositoryException
*/
public boolean isValidAuthCode(final OAuthTokenRequest oauthRequest)
throws RepositoryException;

/**
* Checks the validity of the client associated with the given request
* @param oauthRequest
* @return
* @throws RepositoryException
*/
public boolean isValidClient(final OAuthTokenRequest oauthRequest);

/**
* Checks the validity of the secret given with the given request
* @param oauthRequest
* @return
* @throws RepositoryException
*/
public boolean isValidSecret(final OAuthTokenRequest oauthRequest);

/**
* Checks the validity of the authN credentials
* associated with the given request
* @param oauthRequest
* @return
* @throws RepositoryException
*/
public boolean isValidCredentials(final OAuthTokenRequest oauthRequest);

}
Expand Up @@ -17,31 +17,41 @@

import static javax.servlet.http.HttpServletResponse.SC_FOUND;
import static javax.ws.rs.core.Response.status;
import static org.apache.oltu.oauth2.as.response.OAuthASResponse.authorizationResponse;
import static org.apache.oltu.oauth2.as.response.OAuthASResponse
.authorizationResponse;
import static org.apache.oltu.oauth2.common.OAuth.OAUTH_REDIRECT_URI;
import static org.apache.oltu.oauth2.common.OAuth.OAUTH_RESPONSE_TYPE;
import static org.apache.oltu.oauth2.common.OAuth.OAUTH_STATE;
import static org.apache.oltu.oauth2.common.error.OAuthError.CodeResponse
.UNSUPPORTED_RESPONSE_TYPE;
import static org.apache.oltu.oauth2.common.message.OAuthResponse.errorResponse;
import static org.apache.oltu.oauth2.common.message.types.ResponseType.CODE;
import static org.apache.oltu.oauth2.common.message.types.ResponseType.TOKEN;
import static org.apache.oltu.oauth2.common.utils.OAuthUtils.isEmpty;
import static org.fcrepo.auth.oauth.Constants.CLIENT_PROPERTY;
import static org.fcrepo.auth.oauth.Constants.OAUTH_WORKSPACE;
import static org.fcrepo.auth.oauth.api.Util.createOauthWorkspace;
import static org.slf4j.LoggerFactory.getLogger;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse.OAuthAuthorizationResponseBuilder;
import org.apache.oltu.oauth2.as.response.OAuthASResponse
.OAuthAuthorizationResponseBuilder;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
Expand All @@ -50,13 +60,6 @@
import org.slf4j.Logger;
import org.springframework.stereotype.Component;

import static org.apache.oltu.oauth2.common.message.OAuthResponse.errorResponse;
import static org.fcrepo.auth.oauth.Constants.CLIENT_PROPERTY;
import static org.fcrepo.auth.oauth.Constants.EXPIRATION_TIMEOUT;
import static org.fcrepo.auth.oauth.Constants.OAUTH_WORKSPACE;
import static org.fcrepo.auth.oauth.api.Util.createOauthWorkspace;
import static org.slf4j.LoggerFactory.getLogger;

/**
* @author ajs6f
* @date Jul 1, 2013
Expand Down Expand Up @@ -101,17 +104,35 @@ public Response getAuthorization(@Context final HttpServletRequest request)
final Set<String> scopes = oauthRequest.getScopes();
saveAuthCode(authCode, scopes, client);
builder.setCode(authCode);
}
if (responseType.equals(TOKEN.toString())) {
builder.setAccessToken(oauthIssuerImpl.accessToken());
builder.setExpiresIn(EXPIRATION_TIMEOUT);
/** as far as I can tell from spec and a number of docs,
* "token" is not a valid response type for the authCode
* endpoint
*/
// } else if (responseType.equals(TOKEN.toString())) {
// builder.setAccessToken(oauthIssuerImpl.accessToken());
// builder.setExpiresIn(EXPIRATION_TIMEOUT);
} else {
String errorDesc =
"Invalid response_type parameter value \"" +
responseType + "\"";
LOGGER.debug(errorDesc);
OAuthProblemException e =
OAuthProblemException
.error(UNSUPPORTED_RESPONSE_TYPE,errorDesc);

e.setRedirectUri(oauthRequest.getParam(OAUTH_REDIRECT_URI));
throw e;
}

final String redirectURI =
oauthRequest.getParam(OAUTH_REDIRECT_URI);

if (oauthRequest.getState() != null) {
builder.setParam(OAUTH_STATE, oauthRequest.getState());
}

final OAuthResponse response =
builder.location(redirectURI).buildQueryMessage();
builder.location(redirectURI).buildQueryMessage() ;
final URI url = new URI(response.getLocationUri());

return status(response.getResponseStatus()).location(url).build();
Expand Down
Expand Up @@ -23,23 +23,23 @@
import static javax.ws.rs.core.Response.status;
import static org.apache.oltu.oauth2.as.response.OAuthASResponse.tokenResponse;
import static org.apache.oltu.oauth2.common.OAuth.OAUTH_GRANT_TYPE;
import static org.apache.oltu.oauth2.common.error.OAuthError.TokenResponse.INVALID_CLIENT;
import static org.apache.oltu.oauth2.common.error.OAuthError.TokenResponse.INVALID_GRANT;
import static org.apache.oltu.oauth2.common.error.OAuthError.TokenResponse.UNAUTHORIZED_CLIENT;
import static org.apache.oltu.oauth2.common.error.OAuthError.TokenResponse
.INVALID_CLIENT;
import static org.apache.oltu.oauth2.common.error.OAuthError.TokenResponse
.INVALID_GRANT;
import static org.apache.oltu.oauth2.common.error.OAuthError.TokenResponse
.UNAUTHORIZED_CLIENT;
import static org.apache.oltu.oauth2.common.message.OAuthResponse.errorResponse;
import static org.apache.oltu.oauth2.common.message.types.GrantType.AUTHORIZATION_CODE;
import static org.apache.oltu.oauth2.common.message.types.GrantType
.AUTHORIZATION_CODE;
import static org.fcrepo.auth.oauth.Constants.CLIENT_PROPERTY;
import static org.fcrepo.auth.oauth.Constants.OAUTH_WORKSPACE;
import static org.fcrepo.auth.oauth.Constants.PRINCIPAL_PROPERTY;
import static org.fcrepo.auth.oauth.api.Util.createOauthWorkspace;
import static org.slf4j.LoggerFactory.getLogger;

import java.security.AccessControlException;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -61,7 +61,10 @@
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.fcrepo.AbstractResource;
import org.fcrepo.auth.oauth.TokenRequestValidations;
import org.fcrepo.auth.oauth.impl.DefaultTokenRequestValidations;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
Expand All @@ -73,10 +76,22 @@
public class TokenEndpoint extends AbstractResource {

public static final String INVALID_CLIENT_DESCRIPTION =
"Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).";
"Client authentication failed (e.g., unknown client, " +
"no client authentication included, " +
"or unsupported authentication method).";

private static final Logger LOGGER = getLogger(TokenEndpoint.class);

@Autowired(required = false)
private TokenRequestValidations requestValidator;

@PostConstruct
void defaultValidations() {
if (requestValidator == null) {
requestValidator = new DefaultTokenRequestValidations(sessions);
}
}

/**
* @param request An HTTP request
* @return A token-bearing HTTP response
Expand All @@ -98,8 +113,7 @@ public Response getToken(@Context final HttpServletRequest request) throws
try {
oauthRequest = new OAuthTokenRequest(request);

// TODO check if clientid is valid
if (isNotValid()) {
if (!requestValidator.isValidClient(oauthRequest)) {
final OAuthResponse response =
OAuthASResponse.errorResponse(SC_BAD_REQUEST).setError(
INVALID_CLIENT).setErrorDescription(
Expand All @@ -108,8 +122,7 @@ public Response getToken(@Context final HttpServletRequest request) throws
response.getBody()).build();
}

// TODO check if client_secret is valid
if (isNotValid()) {
if (!requestValidator.isValidSecret(oauthRequest)) {
final OAuthResponse response =
OAuthASResponse
.errorResponse(SC_UNAUTHORIZED)
Expand All @@ -120,10 +133,9 @@ public Response getToken(@Context final HttpServletRequest request) throws
response.getBody()).build();
}

// do checking for different grant types
if (oauthRequest.getParam(OAUTH_GRANT_TYPE).equals(
AUTHORIZATION_CODE.toString())) {
if (!isValidAuthCode(oauthRequest)) {
if (!requestValidator.isValidAuthCode(oauthRequest)) {
final OAuthResponse response =
errorResponse(SC_BAD_REQUEST).setError(
INVALID_GRANT).setErrorDescription(
Expand All @@ -134,8 +146,7 @@ public Response getToken(@Context final HttpServletRequest request) throws
}
} else if (oauthRequest.getParam(OAUTH_GRANT_TYPE).equals(
GrantType.PASSWORD.toString())) {
// TODO check if username/password is valid
if (isNotValid()) {
if (!requestValidator.isValidCredentials(oauthRequest)) {
final OAuthResponse response =
errorResponse(SC_BAD_REQUEST).setError(
INVALID_GRANT).setErrorDescription(
Expand Down Expand Up @@ -174,47 +185,6 @@ public Response getToken(@Context final HttpServletRequest request) throws
}
}

/**
* @param oauthRequest
* @return An answer to whether or not this request matches up with an
* authorization code issued at the {@link AuthzEndpoint}
* @throws RepositoryException
*/
private boolean isValidAuthCode(final OAuthTokenRequest oauthRequest)
throws RepositoryException {
final String client = oauthRequest.getClientId();
LOGGER.debug("Request has authorization client: {}", client);
final String code = oauthRequest.getCode();
final Set<String> scopes = oauthRequest.getScopes();
final Session session = sessions.getSession(OAUTH_WORKSPACE);
try {
final Node authCodeNode =
session.getNode("/authorization-codes/" + code);
LOGGER.debug("Found authorization code node stored: {}",
authCodeNode.getPath());
// if the client is right
if (authCodeNode.getProperty(CLIENT_PROPERTY).getString().equals(
client)) {
// final Set<String> storedScopes =
// newHashSet(map(authCodeNode
// .getProperty(SCOPES_PROPERTY).getValues(),
// value2string));
// and if there is at least one scope in common
// if (intersection(storedScopes, scopes).size() > 0) {
return true;
// }
}
} catch (final PathNotFoundException e) {
// this wasn't a code we stored
return false;
} finally {
session.logout();
}
throw new AccessControlException(
"Could not establish validity or invalidity of authorization code! Code:" +
code);
}

/**
* Stores a token for later use by the configured {@link OAuthRSProvider}
*
Expand All @@ -238,11 +208,6 @@ private void saveToken(final String token, final String client,

}

private boolean isNotValid() {
// TODO actually do some checking of client ID and secret and so forth
return false;
}

/**
* Create the OAuth workspace in JCR to store all our tokens
* @throws RepositoryException
Expand Down

0 comments on commit b8be39c

Please sign in to comment.