Package org.jboss.seam.security.external.oauth

Source Code of org.jboss.seam.security.external.oauth.OAuthAuthenticatorImpl

/*
* JBoss, Home of Professional Open Source
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 org.jboss.seam.security.external.oauth;

import static com.google.common.collect.Iterables.getOnlyElement;

import java.io.IOException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.BeanManager;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;

import org.jboss.seam.security.AuthenticationException;
import org.jboss.seam.security.Authenticator;
import org.jboss.seam.security.BaseAuthenticator;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.events.DeferredAuthenticationEvent;
import org.jboss.seam.security.external.oauth.api.OAuthAuthenticator;
import org.jboss.seam.security.management.picketlink.IdentitySessionProducer;
import org.jboss.seam.social.MultiServicesManager;
import org.jboss.seam.social.SeamSocialExtension;
import org.jboss.seam.social.SocialNetworkServicesHub;
import org.jboss.seam.social.oauth.OAuthService;
import org.jboss.seam.social.oauth.OAuthSession;
import org.jboss.solder.core.Requires;
import org.jboss.solder.logging.Logger;
import org.picketlink.idm.api.Group;
import org.picketlink.idm.api.IdentitySession;
import org.picketlink.idm.api.Role;
import org.picketlink.idm.api.RoleType;
import org.picketlink.idm.api.User;
import org.picketlink.idm.common.exception.FeatureNotSupportedException;
import org.picketlink.idm.common.exception.IdentityException;

import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;

/**
* An Authenticator implementation that uses OAuth to authenticate the user.
*
* Based on OpenIdAuthenticator from Seam Security External module.
*
* The OAuthAuthenticatorImpl has two modes of operation, depending on the value of the serviceName 1. Using the only configured
* OAuthService if serviceName is null, this will raise an IllegalStateException if there is no or more than one available @ServiceRelated
* OAuthService. 2. Using the multiServicesManager, in which case the serviceName selects the service which which to create a
* new connection. This beans exists only if Seam Social is in the classpath
*
* @author maschmid
* @author Antoine Sabot-Durand
*
*/
@Requires("org.jboss.seam.social.oauth.OAuthService")
@Named("oauthAuthenticator")
@SessionScoped
public class OAuthAuthenticatorImpl extends BaseAuthenticator implements OAuthAuthenticator, Authenticator, Serializable {

    private static final long serialVersionUID = 3431696230531662201L;

    @Inject
    @Any
    private Instance<OAuthService> serviceInstances;

    private String serviceName = null;

    /**
     * If this property is set to true (the default) then user roles and attributes will be managed using the Identity
     * Management API.
     */
    private boolean identityManaged = true;

    @Inject
    Instance<Identity> identity;
 
    @Inject
    MultiServicesManager multiServicesManager;

    @Inject
    Instance<IdentitySession> identitySession;

    @Inject
    Instance<IdentitySessionProducer> identitySessionProducer;

    @Inject
    Logger log;

    @Inject
    SeamSocialExtension extension;

    @Inject
    BeanManager beanManager;

    public boolean isIdentityManaged() {
        return identityManaged;
    }

    public void setIdentityManaged(boolean identityManaged) {
        this.identityManaged = identityManaged;
    }

    @Override
    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    @Override
    public String getServiceName() {
        return serviceName;
    }

    @Override
    public List<String> getListOfServices() {
        return multiServicesManager.getListOfServices();
    }

    private OAuthService getUnambiguousService() {
        // Attempts to get the only configured service
        if (extension.getSocialRelated().size() == 1) {
            String name = getOnlyElement(extension.getSocialRelated());
            Annotation qualifier = SeamSocialExtension.getServicesToQualifier().inverse().get(name);
            return serviceInstances.select(qualifier).get();
        } else {
            throw new IllegalStateException("Service name not set and there is no unambiguous OAuthService available");
        }
    }

    private OAuthService getCurrentService() {
        if (serviceName == null) {
            return getUnambiguousService();
        } else {
            return multiServicesManager.getCurrentService();
        }
    }

    @Override
    public void authenticate() {

        String authorizationUrl;

        if (serviceName == null) {
            log.debug("Service name null, authenticating with unamgiguous oauthService");
            OAuthService oauthService = getUnambiguousService();
            authorizationUrl = oauthService.getAuthorizationUrl();
        } else {
            log.debug("authenticating service \"" + serviceName + "\"");
            authorizationUrl = multiServicesManager.initNewSession(serviceName);
        }

        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(authorizationUrl);
            setStatus(AuthenticationStatus.DEFERRED);
        } catch (IOException e) {
            log.error("Failed to redirect ", e);
            setStatus(AuthenticationStatus.FAILURE);
        }
    }

  
   
    @Override
    public String getVerifierParamName() {
        return getCurrentHub().getVerifierParamName();
    }

    private SocialNetworkServicesHub getCurrentHub() {
    return multiServicesManager.getCurrentServiceHub();
  }

  @Override
    public String getVerifier() {
        return getCurrentService().getVerifier();
    }

    @Override
    public void setVerifier(String verifier) {
        getCurrentService().setVerifier(verifier);
    }

    @Override
    public void connect() {

        OAuthService currentService;
        OAuthSession currentSession;

        if (serviceName != null) {
            MultiServicesManager manager = multiServicesManager;
            manager.connectCurrentService();

            currentService = manager.getCurrentService();
            currentSession = manager.getCurrentSession();
        } else {
            currentService = getUnambiguousService();
            currentSession = currentService.getSession();

            currentService.initAccessToken();
        }

        OAuthUser user = new OAuthUser(currentService.getType(), currentSession.getUserProfile());

        if (isIdentityManaged()) {
            // By default we set the status to FAILURE, if we manage to get to the end
            // of this method we get rewarded with a SUCCESS
            setStatus(AuthenticationStatus.FAILURE);

            if (identitySessionProducer.get().isConfigured()) {
                validateManagedUser(user);
            }
        }

        setUser(user);
        setStatus(AuthenticationStatus.SUCCESS);

        beanManager.fireEvent(new DeferredAuthenticationEvent(true));
    }

    protected void validateManagedUser(OAuthUser principal) {
        IdentitySession session = identitySession.get();

        try {
            // Check that the user's identity exists
            if (session.getPersistenceManager().findUser(principal.getId()) == null) {
                // The user wasn't found, let's create them

                User user = session.getPersistenceManager().createUser(principal.getId());

                // TODO allow the OAuth -> IDM attribute mapping to be configured
                // e.g.
                // session.getAttributesManager().addAttribute(user, "fullName", principal.getUserProfile().getFullName());
                // session.getAttributesManager().addAttribute(user, "profileImageUrl",
                // principal.getUserProfile().getProfileImageUrl());

                // Load the user's roles and groups
                try {
                    Collection<RoleType> roleTypes = session.getRoleManager().findUserRoleTypes(user);

                    for (RoleType roleType : roleTypes) {
                        for (Role role : session.getRoleManager().findRoles(user, roleType)) {
                            identity.get().addRole(role.getRoleType().getName(), role.getGroup().getName(),
                                    role.getGroup().getGroupType());
                        }
                    }

                    for (Group g : session.getRelationshipManager().findAssociatedGroups(user)) {
                        identity.get().addGroup(g.getName(), g.getGroupType());
                    }
                } catch (FeatureNotSupportedException ex) {
                    throw new AuthenticationException("Error loading user's roles and groups", ex);
                } catch (IdentityException ex) {
                    throw new AuthenticationException("Error loading user's roles and groups", ex);
                }

            }
        } catch (IdentityException ex) {
            throw new AuthenticationException("Error locating User record for OAuth user", ex);
        }
    }
}
TOP

Related Classes of org.jboss.seam.security.external.oauth.OAuthAuthenticatorImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.