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

net.krotscheck.kangaroo.authz.oauth2.resource.token.OwnerCredentialsGrantHandler Maven / Gradle / Ivy

/*
 * Copyright (c) 2016 Michael Krotscheck
 *
 * 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 net.krotscheck.kangaroo.authz.oauth2.resource.token;

import net.krotscheck.kangaroo.authz.common.authenticator.AuthenticatorType;
import net.krotscheck.kangaroo.authz.common.authenticator.IAuthenticator;
import net.krotscheck.kangaroo.authz.common.authenticator.password.PasswordAuthenticator;
import net.krotscheck.kangaroo.authz.common.database.entity.ApplicationScope;
import net.krotscheck.kangaroo.authz.common.database.entity.Authenticator;
import net.krotscheck.kangaroo.authz.common.database.entity.Client;
import net.krotscheck.kangaroo.authz.common.database.entity.ClientType;
import net.krotscheck.kangaroo.authz.common.database.entity.OAuthToken;
import net.krotscheck.kangaroo.authz.common.database.entity.OAuthTokenType;
import net.krotscheck.kangaroo.authz.common.database.entity.UserIdentity;
import net.krotscheck.kangaroo.authz.common.util.ValidationUtil;
import net.krotscheck.kangaroo.authz.oauth2.exception.RFC6749.InvalidGrantException;
import net.krotscheck.kangaroo.authz.oauth2.resource.TokenResponseEntity;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.hibernate.Session;

import javax.inject.Inject;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import java.util.SortedMap;

/**
 * This token type handler takes care of the "password" grant_type
 * OAuth flow. For situations in which a user/password is preferred, we offer
 * a simplified login mechanism, though we do not encourage its use.
 *
 * @author Michael Krotscheck
 */
public final class OwnerCredentialsGrantHandler {

    /**
     * Hibernate session, injected.
     */
    private final Session session;

    /**
     * Current request URI.
     */
    private final UriInfo uriInfo;

    /**
     * injection manager, injected.
     */
    private final InjectionManager injector;

    /**
     * Create a new instance of this token handler.
     *
     * @param session  Injected hibernate session.
     * @param uriInfo  The URI info for the current request.
     * @param injector The injection manager.
     */
    @Inject
    public OwnerCredentialsGrantHandler(final Session session,
                                        @Context final UriInfo uriInfo,
                                        final InjectionManager injector) {
        this.session = session;
        this.uriInfo = uriInfo;
        this.injector = injector;
    }

    /**
     * Apply the client credentials flow to this request.
     *
     * @param client   The Client to use.
     * @param scope    The requested scopes.
     * @param state    The state.
     * @param username The user name.
     * @param password The password.
     * @return A response indicating the result of the request.
     */
    public TokenResponseEntity handle(final Client client,
                                      final String scope,
                                      final String state,
                                      final String username,
                                      final String password) {
        // Make sure the client is the correct type.
        if (!client.getType().equals(ClientType.OwnerCredentials)) {
            throw new InvalidGrantException();
        }

        // Get the authenticator impl.
        IAuthenticator authenticator =
                injector.getInstance(PasswordAuthenticator.class);

        // Pull the password authenticator configuration.
        Authenticator authConfig = ValidationUtil
                .validateAuthenticator(AuthenticatorType.Password,
                        client.getAuthenticators());

        UserIdentity identity;
        MultivaluedStringMap formData = new MultivaluedStringMap();
        formData.putSingle("username", username);
        formData.putSingle("password", password);
        // Try to resolve a user identity. No callback.
        identity = authenticator.authenticate(authConfig, formData, null);
        if (identity == null) {
            throw new NotAuthorizedException(Response.status(Status
                    .UNAUTHORIZED).build());
        }

        // Make sure all requested scopes are permitted for this user.
        SortedMap requestedScopes =
                ValidationUtil.validateScope(scope,
                        identity.getUser().getRole());

        // Go ahead and create the token.
        OAuthToken token = new OAuthToken();
        token.setClient(client);
        token.setTokenType(OAuthTokenType.Bearer);
        token.setExpiresIn(client.getAccessTokenExpireIn());
        token.setScopes(requestedScopes);
        token.setIdentity(identity);
        token.setIssuer(uriInfo.getAbsolutePath().getHost());

        OAuthToken refreshToken = new OAuthToken();
        refreshToken.setClient(client);
        refreshToken.setTokenType(OAuthTokenType.Refresh);
        refreshToken.setExpiresIn(client.getRefreshTokenExpireIn());
        refreshToken.setScopes(token.getScopes());
        refreshToken.setAuthToken(token);
        refreshToken.setIdentity(identity);
        refreshToken.setIssuer(uriInfo.getAbsolutePath().getHost());

        session.save(token);
        session.save(refreshToken);

        return TokenResponseEntity.factory(token, refreshToken, state);
    }

    /**
     * HK2 Binder for our injector context.
     */
    public static final class Binder extends AbstractBinder {

        @Override
        protected void configure() {
            bind(OwnerCredentialsGrantHandler.class)
                    .to(OwnerCredentialsGrantHandler.class)
                    .in(RequestScoped.class);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy