Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 085c1d6
Showing
14 changed files
with
791 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
target/ | ||
.classpath | ||
.settings/ | ||
.project | ||
.metadata | ||
ActiveMQ/ | ||
FedoraRepository/ | ||
indexes/ | ||
ObjectStore/ | ||
*/.cache | ||
.cache | ||
.DS_Store | ||
*~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.fcrepo</groupId> | ||
<artifactId>fcrepo</artifactId> | ||
<version>4.0-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>fcrepo-auth-oauth</artifactId> | ||
<name>Apache Oltu OAuth2 module for Fedora Commons</name> | ||
<dependencies> | ||
<dependency> | ||
<artifactId>fcrepo-http-api</artifactId> | ||
<groupId>org.fcrepo</groupId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.oltu.oauth2</groupId> | ||
<artifactId>org.apache.oltu.oauth2.authzserver</artifactId> | ||
<version>0.31-SNAPSHOT</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.oltu.oauth2</groupId> | ||
<artifactId>oltu-oauth2-resourceserver-filter</artifactId> | ||
<version>0.31-SNAPSHOT</version> | ||
</dependency> | ||
|
||
|
||
<!-- test gear --> | ||
<dependency> | ||
<groupId>org.fcrepo</groupId> | ||
<artifactId>fcrepo-kernel</artifactId> | ||
<version>${project.version}</version> | ||
<classifier>tests</classifier> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.fcrepo</groupId> | ||
<artifactId>fcrepo-http-commons</artifactId> | ||
<version>${project.version}</version> | ||
<scope>test</scope> | ||
<type>test-jar</type> | ||
</dependency> | ||
<dependency> | ||
<groupId>javax.servlet</groupId> | ||
<artifactId>javax.servlet-api</artifactId> | ||
<version>3.0.1</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.sun.grizzly</groupId> | ||
<artifactId>grizzly-servlet-webserver</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.sun.jersey</groupId> | ||
<artifactId>jersey-grizzly</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>javax.mail</groupId> | ||
<artifactId>mail</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.sun.jersey.contribs</groupId> | ||
<artifactId>jersey-spring</artifactId> | ||
<scope>test</scope> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.springframework</groupId> | ||
<artifactId>spring-core</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework</groupId> | ||
<artifactId>spring-test</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.httpcomponents</groupId> | ||
<artifactId>httpclient</artifactId> | ||
</dependency> | ||
<!-- This dependency is for compile-time: it keeps this module independent | ||
of any given choice of JAX-RS implementation. It must be _after_ the test | ||
gear. Otherwise it will get loaded during test phase, but because this is | ||
just an API, the tests will not be able to execute. --> | ||
<dependency> | ||
<groupId>javax</groupId> | ||
<artifactId>javaee-api</artifactId> | ||
</dependency> | ||
</dependencies> | ||
<repositories> | ||
<repository> | ||
<id>Apache Snapshots</id> | ||
<url>https://repository.apache.org/content/repositories/snapshots/</url> | ||
<snapshots> | ||
<enabled>true</enabled> | ||
</snapshots> | ||
</repository> | ||
</repositories> | ||
</project> |
93 changes: 93 additions & 0 deletions
93
src/main/java/org/fcrepo/auth/oauth/api/AuthzEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
|
||
package org.fcrepo.auth.oauth.api; | ||
|
||
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.common.OAuth.OAUTH_REDIRECT_URI; | ||
import static org.apache.oltu.oauth2.common.OAuth.OAUTH_RESPONSE_TYPE; | ||
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 java.net.URI; | ||
import java.net.URISyntaxException; | ||
|
||
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.servlet.http.HttpServletRequest; | ||
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; | ||
import org.apache.oltu.oauth2.common.exception.OAuthProblemException; | ||
import org.apache.oltu.oauth2.common.exception.OAuthSystemException; | ||
import org.apache.oltu.oauth2.common.message.OAuthResponse; | ||
import org.springframework.stereotype.Component; | ||
|
||
import static org.apache.oltu.oauth2.common.message.OAuthResponse.errorResponse; | ||
|
||
@Component | ||
@Path("/authorization") | ||
public class AuthzEndpoint { | ||
|
||
@GET | ||
public Response authorize(@Context | ||
final HttpServletRequest request) throws URISyntaxException, | ||
OAuthSystemException { | ||
|
||
OAuthAuthzRequest oauthRequest = null; | ||
|
||
final OAuthIssuerImpl oauthIssuerImpl = | ||
new OAuthIssuerImpl(new MD5Generator()); | ||
|
||
try { | ||
oauthRequest = new OAuthAuthzRequest(request); | ||
|
||
//build response according to response_type | ||
final String responseType = | ||
oauthRequest.getParam(OAUTH_RESPONSE_TYPE); | ||
|
||
final OAuthASResponse.OAuthAuthorizationResponseBuilder builder = | ||
authorizationResponse(request, SC_FOUND); | ||
|
||
if (responseType.equals(CODE.toString())) { | ||
builder.setCode(oauthIssuerImpl.authorizationCode()); | ||
} | ||
if (responseType.equals(TOKEN.toString())) { | ||
builder.setAccessToken(oauthIssuerImpl.accessToken()); | ||
builder.setExpiresIn(3600l); | ||
} | ||
|
||
final String redirectURI = | ||
oauthRequest.getParam(OAUTH_REDIRECT_URI); | ||
|
||
final OAuthResponse response = | ||
builder.location(redirectURI).buildQueryMessage(); | ||
final URI url = new URI(response.getLocationUri()); | ||
|
||
return status(response.getResponseStatus()).location(url).build(); | ||
|
||
} catch (final OAuthProblemException e) { | ||
|
||
final Response.ResponseBuilder responseBuilder = status(SC_FOUND); | ||
|
||
final String redirectUri = e.getRedirectUri(); | ||
|
||
if (isEmpty(redirectUri)) { | ||
throw new WebApplicationException(responseBuilder.entity( | ||
"OAuth callback url needs to be provided by client!!!") | ||
.build()); | ||
} | ||
final OAuthResponse response = | ||
errorResponse(SC_FOUND).error(e).location(redirectUri) | ||
.buildQueryMessage(); | ||
final URI location = new URI(response.getLocationUri()); | ||
return responseBuilder.location(location).build(); | ||
} | ||
} | ||
|
||
} |
152 changes: 152 additions & 0 deletions
152
src/main/java/org/fcrepo/auth/oauth/api/TokenEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
|
||
package org.fcrepo.auth.oauth.api; | ||
|
||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; | ||
import static javax.servlet.http.HttpServletResponse.SC_OK; | ||
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; | ||
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED; | ||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON; | ||
import static javax.ws.rs.core.Response.status; | ||
|
||
import javax.jcr.RepositoryException; | ||
import javax.jcr.Session; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.ws.rs.Consumes; | ||
import javax.ws.rs.POST; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.core.Context; | ||
import javax.ws.rs.core.Response; | ||
|
||
import static org.apache.oltu.oauth2.as.response.OAuthASResponse.tokenResponse; | ||
import static org.apache.oltu.oauth2.common.message.OAuthResponse.errorResponse; | ||
import static org.apache.oltu.oauth2.common.OAuth.OAUTH_GRANT_TYPE; | ||
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 org.apache.oltu.oauth2.as.issuer.MD5Generator; | ||
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer; | ||
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl; | ||
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest; | ||
import org.apache.oltu.oauth2.as.response.OAuthASResponse; | ||
import org.apache.oltu.oauth2.common.OAuth; | ||
import org.apache.oltu.oauth2.common.exception.OAuthProblemException; | ||
import org.apache.oltu.oauth2.common.exception.OAuthSystemException; | ||
import org.apache.oltu.oauth2.common.message.OAuthResponse; | ||
import org.apache.oltu.oauth2.common.message.types.GrantType; | ||
import org.fcrepo.AbstractResource; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@Path("/token") | ||
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)."; | ||
|
||
@POST | ||
@Consumes(APPLICATION_FORM_URLENCODED) | ||
@Produces(APPLICATION_JSON) | ||
public Response authorize(@Context | ||
final HttpServletRequest request) throws OAuthSystemException, | ||
RepositoryException { | ||
|
||
OAuthTokenRequest oauthRequest = null; | ||
|
||
final OAuthIssuer oauthIssuerImpl = | ||
new OAuthIssuerImpl(new MD5Generator()); | ||
|
||
try { | ||
oauthRequest = new OAuthTokenRequest(request); | ||
|
||
// TODO check if clientid is valid | ||
if (isValid()) { | ||
final OAuthResponse response = | ||
OAuthASResponse.errorResponse(SC_BAD_REQUEST).setError( | ||
INVALID_CLIENT).setErrorDescription( | ||
INVALID_CLIENT_DESCRIPTION).buildJSONMessage(); | ||
return status(response.getResponseStatus()).entity( | ||
response.getBody()).build(); | ||
} | ||
|
||
// TODO check if client_secret is valid | ||
if (isValid()) { | ||
final OAuthResponse response = | ||
OAuthASResponse | ||
.errorResponse(SC_UNAUTHORIZED) | ||
.setError(UNAUTHORIZED_CLIENT) | ||
.setErrorDescription(INVALID_CLIENT_DESCRIPTION) | ||
.buildJSONMessage(); | ||
return status(response.getResponseStatus()).entity( | ||
response.getBody()).build(); | ||
} | ||
|
||
// do checking for different grant types | ||
if (oauthRequest.getParam(OAUTH_GRANT_TYPE).equals( | ||
GrantType.AUTHORIZATION_CODE.toString())) { | ||
// TODO check if authzcode is valid | ||
if (isValid()) { | ||
final OAuthResponse response = | ||
errorResponse(SC_BAD_REQUEST).setError( | ||
INVALID_GRANT).setErrorDescription( | ||
"invalid authorization code") | ||
.buildJSONMessage(); | ||
return status(response.getResponseStatus()).entity( | ||
response.getBody()).build(); | ||
} | ||
} else if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals( | ||
GrantType.PASSWORD.toString())) { | ||
// TODO check if username/password is valid | ||
if (isValid()) { | ||
final OAuthResponse response = | ||
errorResponse(SC_BAD_REQUEST).setError( | ||
INVALID_GRANT).setErrorDescription( | ||
"invalid username or password") | ||
.buildJSONMessage(); | ||
return status(response.getResponseStatus()).entity( | ||
response.getBody()).build(); | ||
} | ||
} else if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals( | ||
GrantType.REFRESH_TOKEN.toString())) { | ||
// refresh token is not supported in this implementation | ||
final OAuthResponse response = | ||
errorResponse(SC_BAD_REQUEST).setError(INVALID_GRANT) | ||
.setErrorDescription( | ||
"invalid username or password") | ||
.buildJSONMessage(); | ||
return status(response.getResponseStatus()).entity( | ||
response.getBody()).build(); | ||
} | ||
final String token = oauthIssuerImpl.accessToken(); | ||
saveToken(token); | ||
final OAuthResponse response = | ||
tokenResponse(SC_OK).setAccessToken(token).setExpiresIn( | ||
"3600").buildJSONMessage(); | ||
return status(response.getResponseStatus()).entity( | ||
response.getBody()).build(); | ||
|
||
} catch (final OAuthProblemException e) { | ||
final OAuthResponse res = | ||
errorResponse(SC_BAD_REQUEST).error(e).buildJSONMessage(); | ||
return status(res.getResponseStatus()).entity(res.getBody()) | ||
.build(); | ||
} | ||
} | ||
|
||
private void saveToken(final String token) throws RepositoryException { | ||
final Session session = sessions.getSession(); | ||
try { | ||
jcrTools.findOrCreateNode(session, "/tokens/" + token); | ||
session.save(); | ||
} finally { | ||
session.logout(); | ||
} | ||
|
||
} | ||
|
||
private boolean isValid() { | ||
// TODO actually do some checking of client ID and secret and so forth | ||
return false; | ||
} | ||
|
||
} |
Oops, something went wrong.