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

org.picketlink.http.internal.authentication.schemes.TokenAuthenticationScheme Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file 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.picketlink.http.internal.authentication.schemes;

import org.picketlink.Identity;
import org.picketlink.authentication.AuthenticationException;
import org.picketlink.config.http.TokenAuthenticationConfiguration;
import org.picketlink.credential.DefaultLoginCredentials;
import org.picketlink.http.authentication.HttpAuthenticationScheme;
import org.picketlink.idm.credential.Token;
import org.picketlink.idm.credential.TokenCredential;

import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

import static org.picketlink.idm.credential.Token.Builder.create;
import static org.picketlink.idm.credential.Token.Consumer;
import static org.picketlink.idm.credential.Token.Provider;

/**
 * 

A custom {@link org.picketlink.http.authentication.HttpAuthenticationScheme} that knows how to extract a header from * the request containing a token to authenticate/re-authenticate an user.

* *

Tokens are issued by providing specific credentials for the primary authentication scheme. This scheme will be used * to validate user's credentials (eg.: username/password over BASIC) and if successful, issue a token.

* *

By default, the primary authentication scheme is {@link org.picketlink.http.internal.authentication.schemes.BasicAuthenticationScheme}. In order to * change it, subclasses may override the getPrimaryAuthenticationScheme method.

* *

Once a token is issued, it will be written to the {@link javax.servlet.http.HttpServletResponse} using a JSON format. In order to * change how tokens are returned to clients, subclasses may override the {@link org.picketlink.http.internal.authentication.schemes.TokenAuthenticationScheme#writeToken(String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}.

* *

This scheme is used by the {@link org.picketlink.http.internal.SecurityFilter}, which is configured in the web application * deployment descriptor (web.xml).

* * @author Pedro Igor */ public class TokenAuthenticationScheme implements HttpAuthenticationScheme { public static final String AUTHORIZATION_TOKEN_HEADER_NAME = "Authorization"; public static final String AUTHENTICATION_SCHEME_NAME = "Token"; public static final String REQUIRES_AUTHENTICATION_HEADER_NAME = "WWW-Authenticate"; @Inject private Instance identityInstance; @Inject private Instance credentialsInstance; @Inject private BasicAuthenticationScheme basicAuthenticationScheme; @Inject private Instance> tokenProvider; @Inject private Instance> tokenConsumer; @Override public void initialize(TokenAuthenticationConfiguration config) { } @Override public void extractCredential(HttpServletRequest request, DefaultLoginCredentials creds) { // we first try to extract the credentials using the primary authentication scheme getPrimaryAuthenticationScheme().extractCredential(request, creds); // if credentials are not present, we try to extract the token from the request. if (creds.getCredential() == null) { String extractedToken = extractTokenFromRequest(request); if (extractedToken != null) { creds.setCredential(createCredential(extractedToken)); } } } /** *

We use a 401 http status code to sinalize to clients that authentication is required.

* *

We only challenge clients if the authentication failed. In other words, if there is a token in the request bu it is * invalid.

* * @param request * @param response * * @throws java.io.IOException */ @Override public void challengeClient(HttpServletRequest request, HttpServletResponse response) { try { if (isPrimaryAuthenticationRequest()) { getPrimaryAuthenticationScheme().challengeClient(request, response); } else { response.setHeader(REQUIRES_AUTHENTICATION_HEADER_NAME, AUTHENTICATION_SCHEME_NAME); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); } } catch (Exception e) { throw new RuntimeException("Could not challeng client credentials.", e); } } @Override public void onPostAuthentication(HttpServletRequest request, HttpServletResponse response) { if (isPrimaryAuthenticationRequest() && getIdentity().isLoggedIn()) { String issuedToken = issueToken(request, response); writeToken(issuedToken, request, response); } } /** *

Returns the current {@link org.picketlink.credential.DefaultLoginCredentials} associated with the request.

* * @return */ protected DefaultLoginCredentials getCredentials() { return this.credentialsInstance.get(); } /** *

Returns the current {@link org.picketlink.Identity} associated with the request.

* * @return */ protected Identity getIdentity() { return this.identityInstance.get(); } /** *

Returns the primary {@link org.picketlink.http.authentication.HttpAuthenticationScheme} that will be used to validate user's * credential before issuing a new token.

* *

Default authentication scheme is {@link org.picketlink.http.internal.authentication.schemes.BasicAuthenticationScheme}.

* * @return */ protected HttpAuthenticationScheme getPrimaryAuthenticationScheme() { return this.basicAuthenticationScheme; } /** *

Extracts the token from the {@link javax.servlet.http.HttpServletRequest}.

*

Subclasses can override this method to customize how tokens are extracted from the request.

* * @param request * @return A String representing the token extracted from the request. */ protected String extractTokenFromRequest(HttpServletRequest request) { String authorizationHeader = request.getHeader(AUTHORIZATION_TOKEN_HEADER_NAME); if (authorizationHeader != null && authorizationHeader.contains(AUTHENTICATION_SCHEME_NAME)) { return authorizationHeader.substring(AUTHENTICATION_SCHEME_NAME.length() + 1); } return null; } /** *

Creates a {@link org.picketlink.idm.credential.TokenCredential} using the token previously extracted from the request.

* *

Subclasses can override this method to customize how the credential is created. Defaults to an instance of {@link org.picketlink.idm.credential.TokenCredential}.

* * @param extractedToken The token previously extracted from the request. * @return */ protected TokenCredential createCredential(String extractedToken) { Token token; Provider tokenProvider = getTokenProvider(); if (tokenProvider != null) { token = create(getTokenProvider().getTokenType().getName(), extractedToken); } else { Consumer tokenConsumer = getTokenConsumer(); if (tokenConsumer == null) { throw new AuthenticationException("You must provide a " + Provider.class.getName() + " or " + Consumer.class.getName() + "."); } token = create(getTokenConsumer().getTokenType().getName(), extractedToken); } return new TokenCredential(token); } /** *

Issues a token for a previously authenticated {@link org.picketlink.idm.model.Account} using the * configured {@link org.picketlink.idm.credential.Token.Provider}.

* * @param request * @param response */ protected String issueToken(HttpServletRequest request, HttpServletResponse response) { Provider tokenProvider = getTokenProvider(); if (tokenProvider == null) { throw new AuthenticationException("No " + Provider.class.getName() + " was found."); } return tokenProvider.issue(getIdentity().getAccount()).getToken(); } /** *

Writes the issuedToken to the {@link javax.servlet.http.HttpServletResponse}.

* * @param issuedToken * @param request * @param response */ protected void writeToken(String issuedToken, HttpServletRequest request, HttpServletResponse response) { try { response.setStatus(HttpServletResponse.SC_OK); PrintWriter writer = response.getWriter(); writer.print("{\"authctoken\":\"" + issuedToken + "\"}"); writer.flush(); } catch (Exception e) { throw new AuthenticationException("Could not write token to response.", e); } } protected Provider getTokenProvider() { if (this.tokenProvider.isAmbiguous()) { throw new AuthenticationException("You must provide exactly one " + Provider.class.getName() + " implementation."); } if (!this.tokenProvider.isUnsatisfied()) { return this.tokenProvider.get(); } return null; } protected Consumer getTokenConsumer() { if (this.tokenConsumer.isAmbiguous()) { throw new AuthenticationException("You must provide exactly one " + Consumer.class.getName() + " implementation."); } if (!this.tokenConsumer.isUnsatisfied()) { return this.tokenConsumer.get(); } return null; } private boolean isPrimaryAuthenticationRequest() { return getCredentials().getCredential() != null && !TokenCredential.class.isInstance(getCredentials().getCredential()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy