All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uiuc.ncsa.myproxy.oa4mp.oauth2.servlet.OA2CertServlet Maven / Gradle / Ivy

The newest version!
package edu.uiuc.ncsa.myproxy.oa4mp.oauth2.servlet;

import edu.uiuc.ncsa.myproxy.MPSingleConnectionProvider;
import edu.uiuc.ncsa.myproxy.oa4mp.oauth2.OA2SE;
import edu.uiuc.ncsa.myproxy.oa4mp.oauth2.OA2ServiceTransaction;
import edu.uiuc.ncsa.myproxy.oa4mp.server.servlet.ACS2;
import edu.uiuc.ncsa.myproxy.oa4mp.server.servlet.AbstractAuthorizationServlet.MyMyProxyLogon;
import edu.uiuc.ncsa.security.core.Identifier;
import edu.uiuc.ncsa.security.core.exceptions.GeneralException;
import edu.uiuc.ncsa.security.core.util.BasicIdentifier;
import edu.uiuc.ncsa.security.delegation.server.ServiceTransaction;
import edu.uiuc.ncsa.security.delegation.server.request.IssuerResponse;
import edu.uiuc.ncsa.security.delegation.servlet.TransactionState;
import edu.uiuc.ncsa.security.delegation.storage.Client;
import edu.uiuc.ncsa.security.delegation.token.AccessToken;
import edu.uiuc.ncsa.security.oauth_2_0.OA2Client;
import edu.uiuc.ncsa.security.oauth_2_0.OA2Errors;
import edu.uiuc.ncsa.security.oauth_2_0.OA2GeneralError;
import edu.uiuc.ncsa.security.oauth_2_0.OA2Scopes;
import edu.uiuc.ncsa.security.oauth_2_0.server.PAIResponse2;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URI;
import java.security.GeneralSecurityException;
import java.util.List;

import static edu.uiuc.ncsa.myproxy.oa4mp.server.ServiceConstantKeys.CONSUMER_KEY;
import static edu.uiuc.ncsa.security.core.util.DateUtils.checkTimestamp;
import static edu.uiuc.ncsa.security.oauth_2_0.OA2Constants.CLIENT_SECRET;

/**
 * 

Created by Jeff Gaynor
* on 2/20/14 at 12:50 PM */ public class OA2CertServlet extends ACS2 { @Override protected AccessToken getAccessToken(HttpServletRequest request) { try { return getServiceEnvironment().getTokenForge().getAccessToken(request); } catch (Throwable t) { // this just means that the access token was not sent as a parameter. It // might have been sent as a bearer token. } List bearerTokens = getAuthHeader(request, "Bearer"); if (bearerTokens.isEmpty()) { throw new GeneralException("Error: no access token"); } if (1 < bearerTokens.size()) { throw new GeneralException("Error: too many access tokens"); } AccessToken at = getServiceEnvironment().getTokenForge().getAccessToken(bearerTokens.get(0)); return at; } /** * This looks for the information about the client and checks the secret. * * @param req * @return */ @Override public Client getClient(HttpServletRequest req) { String rawID = req.getParameter(CONST(CONSUMER_KEY)); String rawSecret = getFirstParameterValue(req, CLIENT_SECRET); // According to the spec. this must be in anBasic Authz header if it is not sent as parameter List basicTokens = getAuthHeader(req, "Basic"); if (2 < basicTokens.size()) { // too many tokens to unscramble throw new OA2GeneralError(OA2Errors.INVALID_TOKEN, "Error: Too many authorization tokens.", HttpStatus.SC_UNAUTHORIZED); //throw new GeneralException("Too many authorization tokens"); } if (rawID == null) { // maybe it was sent as an authorization header // now we have to check for which of these is the identifier for (String x : basicTokens) { try { // Here is some detective work. We get up to TWO basic Authz headers with the id and secret. // Since ids are valid URIs the idea here is anything that is uri must be an id and the other // one is the secret. This also handles the case that one of these is sent as a parameter // in the call and the other is in the header. URI test = URI.create(x); // It is possible that the secret may be parseable as a valid URI (plain strings are // trivially uris). This checks that there a // scheme, which implies this is an id. The other token is assumed to // be the secret. if (test.getScheme() != null) { rawID = x; } else { rawSecret = x; } } catch (Throwable t) { if (rawSecret == null) { rawSecret = x; } } } } if (rawID == null) { throw new OA2GeneralError(OA2Errors.INVALID_REQUEST, "Error: No client id.", HttpStatus.SC_BAD_REQUEST); //throw new UnknownClientException("No client id"); } Identifier id = BasicIdentifier.newID(rawID); OA2Client client = (OA2Client) getClient(id); if (rawSecret == null) { throw new OA2GeneralError(OA2Errors.INVALID_REQUEST, "Error: No secret. request refused.", HttpStatus.SC_BAD_REQUEST); } if (!client.getSecret().equals(DigestUtils.shaHex(rawSecret))) { throw new OA2GeneralError(OA2Errors.INVALID_REQUEST, "Error: Secret is incorrect. request refused.", HttpStatus.SC_BAD_REQUEST); } return client; } public ServiceTransaction verifyAndGet(IssuerResponse iResponse) throws IOException { PAIResponse2 par = (PAIResponse2) iResponse; AccessToken accessToken = par.getAccessToken(); OA2ServiceTransaction t = (OA2ServiceTransaction) getTransactionStore().get(accessToken); if (t == null) { throw new OA2GeneralError(OA2Errors.INVALID_TOKEN, "Invalid access token. Request refused", HttpStatus.SC_UNAUTHORIZED); } if (!t.getScopes().contains(OA2Scopes.SCOPE_MYPROXY)) { // Note that this requires a state, but none is sent in the OA4MP cert request. throw new OA2GeneralError(OA2Errors.INVALID_SCOPE, "Certificate request is not in scope.", HttpStatus.SC_FORBIDDEN); } if (t == null) { throw new OA2GeneralError(OA2Errors.INVALID_TOKEN, "No transaction found for access token \"" + accessToken + "\"", HttpStatus.SC_UNAUTHORIZED); } if (!t.isAccessTokenValid()) { throw new OA2GeneralError(OA2Errors.INVALID_TOKEN, "Invalid access token. Request refused", HttpStatus.SC_UNAUTHORIZED); } checkClient(t.getClient()); // Access tokens must be valid in order to get a cert. If the token is invalid, the user must // get a valid one using the refresh token. checkTimestamp(accessToken.getToken()); return t; } protected void checkMPConnection(OA2ServiceTransaction st) throws GeneralSecurityException { if (!hasMPConnection(st)) { createMPConnection(st.getIdentifier(), st.getMyproxyUsername(), "", st.getLifetime()); } } @Override protected void doRealCertRequest(ServiceTransaction trans, String statusString) throws Throwable { // CIL-243: binding the CR's DN to the user name. Uncomment if we ever decide to do this \ /* if (trans.getCertReq().getCN()==null || (!trans.getUsername().equals(trans.getCertReq().getCN()))) { // CN can be null throw new OA2GeneralError(OA2Errors.INVALID_REQUEST, "The common name on the cert request is \"" + trans.getCertReq().getCN() + "\" which does not match the username \"" + trans.getUsername() + "\"", HttpStatus.SC_BAD_REQUEST); } */ OA2ServiceTransaction st = (OA2ServiceTransaction) trans; OA2SE oa2SE = (OA2SE) getServiceEnvironment(); if (!oa2SE.isTwoFactorSupportEnabled()) { checkMPConnection(st); } else { // The assumption at this point is that the connection information has been stashed, but has not been // used since the password is valid exactly once. Here is where we set up the connection once // and for all. if (!getMyproxyConnectionCache().containsKey(st.getIdentifier())) { throw new GeneralException("No cached my proxy object with identifier " + st.getIdentifierString()); } MPSingleConnectionProvider.MyProxyLogonConnection mpc = (MPSingleConnectionProvider.MyProxyLogonConnection) getMyproxyConnectionCache().get(st.getIdentifier()).getValue(); // First pass will be a MyMyProxyLogon object that allows completing the logon. // After that it will be a regular MyProxyLogon object. Since the password is valid for // a very short period (typically only up to a minute or two), the logon can fail if // not done promptly by the user. if(mpc.getMyProxyLogon() instanceof MyMyProxyLogon) { MyMyProxyLogon myProxyLogon = (MyMyProxyLogon) mpc.getMyProxyLogon(); getMyproxyConnectionCache().remove(mpc.getIdentifier()); createMPConnection(trans.getIdentifier(), myProxyLogon.getUsername(), myProxyLogon.getPassphrase(), trans.getLifetime()); } } doCertRequest(st, statusString); } @Override public void postprocess(TransactionState state) throws Throwable { super.postprocess(state); OA2ServiceTransaction t = (OA2ServiceTransaction) state.getTransaction(); if (((OA2SE) getServiceEnvironment()).isRefreshTokenEnabled() && t.hasRefreshToken()) { // If this has a refresh token, then then do not invalidate the access token, since // users may re-get certs for the lifetime of the refresh token. t.setAccessTokenValid(true); getTransactionStore().save(t); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy