/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.ext.oauth;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import org.json.JSONException;
import org.restlet.Context;
import org.restlet.Response;
import org.restlet.data.CacheDirective;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.ext.oauth.internal.Client;
import org.restlet.ext.oauth.internal.ClientManager;
import org.restlet.ext.oauth.internal.Scopes;
import org.restlet.ext.oauth.internal.TokenManager;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
/**
* Base class for common resources used by the OAuth server side. Implements
* OAuth 2.0 (RFC6749)
*
* @author Shotaro Uchida <fantom@xmaker.mx>
* @author Kristoffer Gronowski
*/
public abstract class OAuthServerResource extends ServerResource implements
OAuthResourceDefs {
public static final String PARAMETER_DEFAULT_SCOPE = "defaultScope";
public static void addCacheDirective(Response response,
CacheDirective cacheDirective) {
List<CacheDirective> cacheDirectives = response.getCacheDirectives();
if (cacheDirectives == null) {
cacheDirectives = new ArrayList<CacheDirective>();
response.setCacheDirectives(cacheDirectives);
}
cacheDirectives.add(cacheDirective);
}
/**
* Returns the representation of the given error. The format of the JSON
* document is according to 5.2. Error Response.
*
* @param ex
* Any OAuthException with error
* @return The representation of the given error.
*/
public static Representation responseErrorRepresentation(OAuthException ex) {
try {
return new JsonRepresentation(ex.createErrorDocument());
} catch (JSONException e) {
StringRepresentation r = new StringRepresentation(
"{\"error\":\"server_error\",\"error_description:\":\""
+ e.getLocalizedMessage() + "\"}");
r.setMediaType(MediaType.APPLICATION_JSON);
return r;
}
}
protected volatile ClientManager clients;
protected volatile TokenManager tokens;
/**
* Default constructor.
*/
public OAuthServerResource() {
super();
}
@Override
protected void doInit() throws ResourceException {
super.doInit();
Context ctx = getContext();
ConcurrentMap<String, Object> attribs = ctx.getAttributes();
clients = (ClientManager) attribs.get(ClientManager.class.getName());
tokens = (TokenManager) attribs.get(TokenManager.class.getName());
getLogger().fine("Found client store = " + clients);
}
/**
* Get request parameter "client_id".
*
* @param params
* @return
* @throws OAuthException
*/
protected Client getClient(Form params) throws OAuthException {
// check clientId:
String clientId = params.getFirstValue(CLIENT_ID);
if (clientId == null || clientId.isEmpty()) {
getLogger().warning("Could not find client ID");
throw new OAuthException(OAuthError.invalid_request,
"No client_id parameter found.", null);
}
Client client = clients.findById(clientId);
getLogger().fine("Client = " + client);
if (client == null) {
getLogger().warning("Need to register the client : " + clientId);
throw new OAuthException(OAuthError.invalid_request,
"Need to register the client : " + clientId, null);
}
return client;
}
/**
* Get request parameter "scope".
*
* @param params
* @return
* @throws OAuthException
*/
protected String[] getScope(Form params) throws OAuthException {
String scope = params.getFirstValue(SCOPE);
if (scope == null || scope.isEmpty()) {
/*
* If the client omits the scope parameter when requesting
* authorization, the authorization server MUST either process the
* request using a pre-defined default value, or fail the request
* indicating an invalid scope... (draft-ietf-oauth-v2-30 3.3.)
*/
Object defaultScope = getContext().getAttributes().get(
PARAMETER_DEFAULT_SCOPE);
if (defaultScope == null || defaultScope.toString().isEmpty()) {
throw new OAuthException(OAuthError.invalid_scope,
"Scope has not provided.", null);
}
scope = defaultScope.toString();
}
return Scopes.parseScope(scope);
}
/**
* Get request parameter "state".
*
* @param params
* @return
* @throws OAuthException
*/
protected String getState(Form params) {
return params.getFirstValue(STATE);
}
}