/*
* Copyright (c) 2005-2008, 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.provider.openid;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.identity.base.IdentityConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.provider.IdentityProviderException;
import org.wso2.carbon.user.core.UserStoreManager;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Contains OpenID related utility functions
*/
public class OpenIDUtil {
private static final Set<Character> UNRESERVED_CHARACTERS = new HashSet<Character>();
private static final Log log = LogFactory.getLog(OpenIDUtil.class);
private static Map<String, String> axMapping = new HashMap<String, String>();
static {
for (char c = 'a'; c <= 'z'; c++)
UNRESERVED_CHARACTERS.add(Character.valueOf(c));
for (char c = 'A'; c <= 'A'; c++)
UNRESERVED_CHARACTERS.add(Character.valueOf(c));
for (char c = '0'; c <= '9'; c++)
UNRESERVED_CHARACTERS.add(Character.valueOf(c));
UNRESERVED_CHARACTERS.add(Character.valueOf('-'));
UNRESERVED_CHARACTERS.add(Character.valueOf('.'));
UNRESERVED_CHARACTERS.add(Character.valueOf('_'));
UNRESERVED_CHARACTERS.add(Character.valueOf('~'));
}
private OpenIDUtil() {
}
/**
* Generate OpenID for a given user.
*
* @param user User
* @return Generated OpenID
* @throws IdentityProviderException
*/
public static String generateOpenID(String user) throws IdentityProviderException {
ServerConfiguration serverConfig = null;
String openIDUserUrl = null;
String openID = null;
URI uri = null;
URL url = null;
String encodedUser = null;
serverConfig = ServerConfiguration.getInstance();
openIDUserUrl = getOpenIDServerURL();
encodedUser = normalizeUrlEncoding(user);
openID = String.format(openIDUserUrl, encodedUser);
try {
uri = new URI(openID);
} catch (URISyntaxException e) {
log.error("Invalid OpenID URL :" + openID, e);
throw new IdentityProviderException("Invalid OpenID URL :" + openID, e);
}
try {
url = uri.normalize().toURL();
if (url.getQuery() != null || url.getRef() != null) {
log.error("Invalid user name for OpenID :" + openID);
throw new IdentityProviderException("Invalid user name for OpenID :" + openID);
}
} catch (MalformedURLException e) {
log.error("Malformed OpenID URL :" + openID, e);
throw new IdentityProviderException("Malformed OpenID URL :" + openID, e);
}
openID = url.toString();
if (log.isDebugEnabled()) {
log.debug("OpenID generated successfully : " + openID);
}
return openID;
}
/**
* @param text
* @return
*/
private static String normalizeUrlEncoding(String text) {
if (text == null) {
return null;
}
int len = text.length();
StringBuilder normalized = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char current = text.charAt(i);
if (current == '%' && i < len - 2) {
String percentCode = text.substring(i, i + 3).toUpperCase();
try {
String str = URLDecoder.decode(percentCode, "ISO-8859-1");
char chr = str.charAt(0);
if (UNRESERVED_CHARACTERS.contains(Character.valueOf(chr))) {
normalized.append(chr);
} else {
normalized.append(percentCode);
}
} catch (UnsupportedEncodingException e) {
normalized.append(percentCode);
}
i += 2;
} else {
normalized.append(current);
}
}
return normalized.toString();
}
/**
* This provides a mapping between http://schema.openid.net/ and
* http://axschema.org
*
* @param val schema name-space URL
* @return mapped value
*/
public static String getMappedAxSchema(String val) {
if (axMapping.containsKey(val)) {
return axMapping.get(val);
}
return val;
}
/**
* Find the OpenID corresponding to the given user name.
*
* @param userName User name
* @return OpenID corresponding the given user name.
* @throws IdentityProviderException
*/
public static String getOpenID(String userName) throws IdentityProviderException {
return generateOpenID(userName);
}
/**
* @param openID
* @return
* @throws Exception
*/
public static String getUserName(String openID) throws MalformedURLException {
// openIDPattern = https://openid:9443/openid/admin
String openIDUrlPath = new URL(openID).getPath();
String contextPath = "/openid";
return openIDUrlPath.substring(openIDUrlPath.indexOf(contextPath) + contextPath.length() + 1,
openIDUrlPath.length());
}
/**
* Verify user name/password authentication.
*
* @param username User name
* @param password Password
* @return true if user successfully authenticated
*/
public static boolean doLogin(String username, String password) {
try {
UserStoreManager userStore = IdentityTenantUtil.getRealm(null, username).getUserStoreManager();
return userStore.authenticate(username, password);
} catch (Exception e) {
log.error("Error while authenticating user", e);
return false;
}
}
public static String getOpenIDServerURL() {
// Read from OpenID configuration in identity.xml
String openIDServerURL = IdentityUtil.getProperty(IdentityConstants.ServerConfig.OPENID_SERVER_URL);
// If configuration are not defined, build URL from server configurations.
if (StringUtils.isBlank(openIDServerURL)) {
openIDServerURL = IdentityUtil.getServerURL(OpenIDServerConstants.OPENID_SERVER, true, true);
}
return openIDServerURL;
}
public static String getOpenIDLoginPageURL() {
// Read from OpenID configuration in identity.xml
String openIDServerURL = IdentityUtil.getProperty(IdentityConstants.ServerConfig.OPENID_LOGIN_PAGE_URL);
// If configuration are not defined, build URL from server configurations.
if (StringUtils.isBlank(openIDServerURL)) {
openIDServerURL = IdentityUtil.getServerURL("/authenticationendpoint/openid_login.do", false, false);
}
return openIDServerURL;
}
public static String getOpenIDUserPattern() {
// Read from OpenID configuration in identity.xml
String openIDUserPattern = IdentityUtil.getProperty(IdentityConstants.ServerConfig.OPENID_USER_PATTERN);
// If configuration are not defined, build URL from server configurations.
if (StringUtils.isBlank(openIDUserPattern)) {
openIDUserPattern = IdentityUtil.getServerURL(OpenIDServerConstants.OPENID, true, true);
}
return openIDUserPattern;
}
}