/*
* Copyright (c) 2013, 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.application.authenticator.openid;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.application.authentication.framework.AbstractApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.FederatedApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.config.ConfigurationFacade;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.AuthenticationFailedException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils;
import org.wso2.carbon.identity.application.authenticator.openid.exception.OpenIDException;
import org.wso2.carbon.identity.application.authenticator.openid.manager.DefaultOpenIDManager;
import org.wso2.carbon.identity.application.authenticator.openid.manager.OpenIDManager;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
public class OpenIDAuthenticator extends AbstractApplicationAuthenticator implements
FederatedApplicationAuthenticator {
private static final long serialVersionUID = 2878862656196592256L;
private static final String OPENID_MANAGER = "OpenIDManager";
private static Log log = LogFactory.getLog(OpenIDAuthenticator.class);
@Override
public boolean canHandle(HttpServletRequest request) {
if (log.isTraceEnabled()) {
log.trace("Inside canHandle()");
}
String opeidMode = request.getParameter(OpenIDAuthenticatorConstants.MODE);
if (opeidMode != null && !"checkid_immediate".equals(opeidMode)
&& !"checkid_setup".equals(opeidMode) && !"check_authentication".equals(opeidMode)) {
return true;
}
return false;
}
@Override
protected void initiateAuthenticationRequest(HttpServletRequest request,
HttpServletResponse response, AuthenticationContext context)
throws AuthenticationFailedException {
OpenIDManager manager = getNewOpenIDManagerInstance();
if (context.getExternalIdP() != null || request.getParameter("claimed_id") != null) {
try {
Map<String, String> authenticatorProperties = context.getAuthenticatorProperties();
if(authenticatorProperties != null){
setOpenIDServerUrl(authenticatorProperties);
}
if (getOpenIDServerUrl() != null) {
// this is useful in case someone wants to overrode the default OpenID
// authenticator.
authenticatorProperties.put(
IdentityApplicationConstants.Authenticator.OpenID.OPEN_ID_URL,
getOpenIDServerUrl());
}
String loginPage = manager.doOpenIDLogin(request, response, context);
String domain = request.getParameter("domain");
if (domain != null) {
loginPage = loginPage + "&fidp=" + domain;
}
if (authenticatorProperties != null) {
String queryString = authenticatorProperties
.get(FrameworkConstants.QUERY_PARAMS);
if (queryString != null) {
if (!queryString.startsWith("&")) {
loginPage = loginPage + "&" + queryString;
} else {
loginPage = loginPage + queryString;
}
}
}
response.sendRedirect(loginPage);
} catch (IOException e) {
log.error("Error when sending to OpenID Provider", e);
throw new AuthenticationFailedException(e.getMessage(), e);
} catch (OpenIDException e) {
log.error("Error when sending to OpenID Provider", e);
throw new AuthenticationFailedException(e.getMessage(), e);
}
} else { // Claimed Identity
String loginPage = ConfigurationFacade.getInstance().getAuthenticationEndpointURL();
String queryParams = FrameworkUtils.getQueryStringWithFrameworkContextId(
context.getQueryParams(), context.getCallerSessionKey(),
context.getContextIdentifier());
try {
// TODO should be able to remove loginType=openid
response.sendRedirect(loginPage + ("?" + queryParams + "&loginType=openid")
+ "&authenticators=" + getName() + ":" + "LOCAL");
} catch (IOException e) {
log.error("Error when sending to the login page", e);
throw new AuthenticationFailedException(e.getMessage(), e);
}
}
return;
}
@Override
protected void processAuthenticationResponse(HttpServletRequest request,
HttpServletResponse response, AuthenticationContext context)
throws AuthenticationFailedException {
OpenIDManager manager = getNewOpenIDManagerInstance();
try {
manager.processOpenIDLoginResponse(request, response, context);
AuthenticatedUser authenticatedSubject = context.getSubject();
String subject = null;
String isSubjectInClaimsProp = context.getAuthenticatorProperties().get(
IdentityApplicationConstants.Authenticator.SAML2SSO.IS_USER_ID_IN_CLAIMS);
if ("true".equalsIgnoreCase(isSubjectInClaimsProp)) {
subject = getSubjectFromUserIDClaimURI(context);
}
if (subject == null) {
subject = authenticatedSubject.getAuthenticatedSubjectIdentifier();
}
if (subject == null) {
throw new OpenIDException("Cannot find federated User Identifier");
}
authenticatedSubject.setAuthenticatedSubjectIdentifier(subject);
} catch (OpenIDException e) {
log.error("Error when processing response from OpenID Provider", e);
throw new AuthenticationFailedException(e.getMessage(), e);
}
}
@Override
public String getContextIdentifier(HttpServletRequest request) {
if (log.isTraceEnabled()) {
log.trace("Inside getContextIdentifier()");
}
return request.getParameter(OpenIDAuthenticatorConstants.SESSION_DATA_KEY);
}
private OpenIDManager getNewOpenIDManagerInstance() {
OpenIDManager openIDManager = null;
String managerClassName = getAuthenticatorConfig().getParameterMap().get(OPENID_MANAGER);
if (managerClassName != null) {
try {
// Bundle class loader will cache the loaded class and returned
// the already loaded instance, hence calling this method
// multiple times doesn't cost.
Class clazz = Thread.currentThread().getContextClassLoader()
.loadClass(managerClassName);
openIDManager = (OpenIDManager) clazz.newInstance();
} catch (ClassNotFoundException e) {
log.error("Error while instantiating the OpenIDManager ", e);
} catch (InstantiationException e) {
log.error("Error while instantiating the OpenIDManager ", e);
} catch (IllegalAccessException e) {
log.error("Error while instantiating the OpenIDManager ", e);
}
} else {
openIDManager = new DefaultOpenIDManager();
}
return openIDManager;
}
@Override
public String getClaimDialectURI() {
return OpenIDAuthenticatorConstants.CLAIM_DIALECT_URI;
}
@Override
public String getFriendlyName() {
return OpenIDAuthenticatorConstants.AUTHENTICATOR_FRIENDLY_NAME;
}
@Override
public String getName() {
return OpenIDAuthenticatorConstants.AUTHENTICATOR_NAME;
}
/**
* @return
*/
protected String getOpenIDServerUrl() {
return null;
}
/**
*
* @param authenticatorProperties
*/
protected void setOpenIDServerUrl(Map<String, String> authenticatorProperties){
}
/**
* @subject
*/
protected String getSubjectFromUserIDClaimURI(AuthenticationContext context) {
String subject = null;
try {
subject = FrameworkUtils.getFederatedSubjectFromClaims(context, getClaimDialectURI());
} catch (Exception e) {
if(log.isDebugEnabled()) {
log.debug("Couldn't find the subject claim from claim mappings ", e);
}
}
return subject;
}
}