org.wso2.carbon.identity.sso.agent.openid.OpenIDManager.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.sso.agent.openid.OpenIDManager.java

Source

/*
 * Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you 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.wso2.carbon.identity.sso.agent.openid;

import org.apache.commons.collections.MapUtils;
import org.openid4java.association.AssociationException;
import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.Discovery;
import org.openid4java.discovery.DiscoveryException;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.discovery.Identifier;
import org.openid4java.discovery.yadis.YadisException;
import org.openid4java.discovery.yadis.YadisResolver;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.AuthSuccess;
import org.openid4java.message.MessageException;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import org.openid4java.server.RealmVerifierFactory;
import org.openid4java.util.HttpFetcherFactory;
import org.wso2.carbon.identity.sso.agent.SSOAgentConstants;
import org.wso2.carbon.identity.sso.agent.SSOAgentDataHolder;
import org.wso2.carbon.identity.sso.agent.SSOAgentException;
import org.wso2.carbon.identity.sso.agent.bean.LoggedInSessionBean;
import org.wso2.carbon.identity.sso.agent.bean.SSOAgentConfig;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OpenIDManager {

    // Smart OpenID Consumer Manager
    AttributesRequestor attributesRequestor = null;
    private SSOAgentConfig ssoAgentConfig = null;

    public OpenIDManager(SSOAgentConfig ssoAgentConfig) throws SSOAgentException {
        SSOAgentDataHolder.getInstance().setConsumerManager(getConsumerManagerInstance());
        this.ssoAgentConfig = ssoAgentConfig;
    }

    private ConsumerManager getConsumerManagerInstance() throws SSOAgentException {

        HttpFetcherFactory httpFetcherFactory = null;
        try {
            httpFetcherFactory = new HttpFetcherFactory(SSLContext.getDefault(), null);
        } catch (NoSuchAlgorithmException e) {
            throw new SSOAgentException("Error while getting default SSL Context", e);
        }
        return new ConsumerManager(new RealmVerifierFactory(new YadisResolver(httpFetcherFactory)), new Discovery(),
                httpFetcherFactory);
    }

    public String doOpenIDLogin(HttpServletRequest request, HttpServletResponse response) throws SSOAgentException {

        String claimedId = ssoAgentConfig.getOpenId().getClaimedId();

        try {
            ConsumerManager manager = SSOAgentDataHolder.getInstance().getConsumerManager();

            if (ssoAgentConfig.getOpenId().isDumbModeEnabled()) {
                // Switch the consumer manager to dumb mode
                manager.setMaxAssocAttempts(0);
            }

            // Discovery on the user supplied ID
            List discoveries = manager.discover(claimedId);

            // Associate with the OP and share a secret
            DiscoveryInformation discovered = manager.associate(discoveries);

            // Keeping necessary parameters to verify the AuthResponse
            LoggedInSessionBean sessionBean = new LoggedInSessionBean();
            sessionBean.setOpenId(sessionBean.new OpenID());
            sessionBean.getOpenId().setDiscoveryInformation(discovered); // set the discovery information
            request.getSession().setAttribute(SSOAgentConstants.SESSION_BEAN_NAME, sessionBean);

            manager.setImmediateAuth(true);
            AuthRequest authReq = manager.authenticate(discovered, ssoAgentConfig.getOpenId().getReturnToURL());

            // Request subject attributes using Attribute Exchange extension specification if AttributeExchange is enabled
            if (ssoAgentConfig.getOpenId().isAttributeExchangeEnabled()
                    && ssoAgentConfig.getOpenId().getAttributesRequestor() != null) {

                attributesRequestor = ssoAgentConfig.getOpenId().getAttributesRequestor();
                attributesRequestor.init();

                String[] requestedAttributes = attributesRequestor.getRequestedAttributes(claimedId);

                // Getting required attributes using FetchRequest
                FetchRequest fetchRequest = FetchRequest.createFetchRequest();

                for (String requestedAttribute : requestedAttributes) {
                    fetchRequest.addAttribute(requestedAttribute,
                            attributesRequestor.getTypeURI(claimedId, requestedAttribute),
                            attributesRequestor.isRequired(claimedId, requestedAttribute),
                            attributesRequestor.getCount(claimedId, requestedAttribute));
                }

                // Adding the AX extension to the AuthRequest message
                authReq.addExtension(fetchRequest);
            }

            // Returning OP Url
            SSOAgentDataHolder.getInstance().setConsumerManager(manager);
            StringBuilder destinationUrl = new StringBuilder(authReq.getDestinationUrl(true));

            if (MapUtils.isNotEmpty(ssoAgentConfig.getQueryParams())) {
                StringBuilder builder = new StringBuilder();
                for (Map.Entry<String, String[]> entry : ssoAgentConfig.getQueryParams().entrySet()) {
                    if (entry.getKey() != null && entry.getValue() != null && entry.getValue().length > 0) {
                        for (String param : entry.getValue()) {
                            builder.append("&").append(entry.getKey()).append("=").append(param);
                        }
                    }
                }
                destinationUrl.append(builder);
            }
            return destinationUrl.toString();

        } catch (YadisException e) {
            if (e.getErrorCode() == 1796) {
                throw new SSOAgentException(e.getMessage(), e);
            }
            throw new SSOAgentException("Error while creating FetchRequest", e);
        } catch (MessageException e) {
            throw new SSOAgentException("Error while creating FetchRequest", e);
        } catch (DiscoveryException e) {
            throw new SSOAgentException("Error while doing OpenID Discovery", e);
        } catch (ConsumerException e) {
            throw new SSOAgentException("Error while doing OpenID Authentication", e);
        }
    }

    public void processOpenIDLoginResponse(HttpServletRequest request, HttpServletResponse response)
            throws SSOAgentException {

        try {
            // Getting all parameters in request including AuthResponse
            ParameterList authResponseParams = new ParameterList(request.getParameterMap());

            // Get previously saved session bean
            LoggedInSessionBean loggedInSessionBean = (LoggedInSessionBean) request.getSession(false)
                    .getAttribute(SSOAgentConstants.SESSION_BEAN_NAME);
            if (loggedInSessionBean == null) {
                throw new SSOAgentException(
                        "Error while verifying OpenID response. " + "Cannot find valid session for user");
            }

            // Previously discovered information
            DiscoveryInformation discovered = loggedInSessionBean.getOpenId().getDiscoveryInformation();

            // Verify return-to, discoveries, nonce & signature
            // Signature will be verified using the shared secret
            VerificationResult verificationResult = SSOAgentDataHolder.getInstance().getConsumerManager()
                    .verify(ssoAgentConfig.getOpenId().getReturnToURL(), authResponseParams, discovered);

            Identifier verified = verificationResult.getVerifiedId();

            // Identifier will be NULL if verification failed
            if (verified != null) {

                AuthSuccess authSuccess = (AuthSuccess) verificationResult.getAuthResponse();

                loggedInSessionBean.getOpenId().setClaimedId(authSuccess.getIdentity());

                // Get requested attributes using AX extension
                if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
                    Map<String, List<String>> attributesMap = new HashMap<String, List<String>>();
                    if (ssoAgentConfig.getOpenId().getAttributesRequestor() != null) {
                        attributesRequestor = ssoAgentConfig.getOpenId().getAttributesRequestor();
                        String[] attrArray = attributesRequestor.getRequestedAttributes(authSuccess.getIdentity());
                        FetchResponse fetchResp = (FetchResponse) authSuccess.getExtension(AxMessage.OPENID_NS_AX);
                        for (String attr : attrArray) {
                            List attributeValues = fetchResp.getAttributeValuesByTypeUri(
                                    attributesRequestor.getTypeURI(authSuccess.getIdentity(), attr));
                            if (attributeValues.get(0) instanceof String
                                    && ((String) attributeValues.get(0)).split(",").length > 1) {
                                String[] splitString = ((String) attributeValues.get(0)).split(",");
                                for (String part : splitString) {
                                    attributeValues.add(part);
                                }
                            }
                            if (attributeValues.get(0) != null) {
                                attributesMap.put(attr, attributeValues);
                            }
                        }
                    }
                    loggedInSessionBean.getOpenId().setSubjectAttributes(attributesMap);
                }

            } else {
                throw new SSOAgentException("OpenID verification failed");
            }

        } catch (AssociationException e) {
            throw new SSOAgentException("Error while verifying OpenID response", e);
        } catch (MessageException e) {
            throw new SSOAgentException("Error while verifying OpenID response", e);
        } catch (DiscoveryException e) {
            throw new SSOAgentException("Error while verifying OpenID response", e);
        }

    }

}