org.callimachusproject.auth.OpenIDAuthReader.java Source code

Java tutorial

Introduction

Here is the source code for org.callimachusproject.auth.OpenIDAuthReader.java

Source

/*
 * Copyright (c) 2012, James Leigh Some rights reserved.
 *
 * 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.callimachusproject.auth;

import static org.callimachusproject.util.PercentCodec.decode;
import static org.callimachusproject.util.PercentCodec.encode;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.callimachusproject.client.HttpUriClient;
import org.callimachusproject.engine.model.TermFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OpenIDAuthReader implements ParameterAuthReader {
    private final Logger logger = LoggerFactory.getLogger(OpenIDAuthReader.class);
    private final HttpUriClient client;
    private final TermFactory tf;
    private final String endpoint;
    private final String realm;

    public OpenIDAuthReader(String self, String endpoint, String realm, HttpUriClient client) {
        this.client = client;
        this.tf = TermFactory.newInstance(endpoint);
        this.endpoint = endpoint;
        this.realm = realm;
    }

    @Override
    public String getLoginPage(String returnTo, boolean loggedIn, String parameters, String[] via) {
        StringBuilder sb = new StringBuilder(endpoint);
        if (endpoint.indexOf('?') < 0) {
            sb.append('?');
        } else {
            sb.append('&');
        }
        sb.append("openid.ns=http://specs.openid.net/auth/2.0");
        if (parameters != null && parameters.contains("openid.mode=setup_needed")) {
            sb.append("&openid.mode=checkid_setup");
        } else if (loggedIn || parameters != null && parameters.contains("openid.mode=id_res")) {
            sb.append("&openid.mode=checkid_immediate");
        } else {
            sb.append("&openid.mode=checkid_setup");
        }
        sb.append("&openid.return_to=").append(encode(returnTo));
        sb.append("&openid.realm=").append(encode(realm));
        sb.append("&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select");
        sb.append("&openid.identity=http://specs.openid.net/auth/2.0/identifier_select");
        sb.append("&openid.ns.ax=http://openid.net/srv/ax/1.0");
        sb.append("&openid.ax.mode=fetch_request");
        sb.append("&openid.ax.required=email,fullname,firstname,lastname");
        sb.append("&openid.ax.type.email=http://axschema.org/contact/email");
        sb.append("&openid.ax.type.fullname=http://axschema.org/namePerson");
        sb.append("&openid.ax.type.firstname=http://axschema.org/namePerson/first");
        sb.append("&openid.ax.type.lastname=http://axschema.org/namePerson/last");
        return sb.toString();
    }

    @Override
    public String getParameters(String method, String uri, String query, HttpEntity body) {
        if ("POST".equals(method) && body != null && body.getContentType() != null
                && "application/x-www-form-urlencoded".equals(body.getContentType().getValue())) {
            try {
                return EntityUtils.toString(body);
            } catch (IOException e) {
                logger.warn(e.toString(), e);
            }
        }
        return query;
    }

    @Override
    public boolean isLoggingIn(String parameters) {
        return parameters.contains("openid.mode=id_res");
    }

    @Override
    public boolean isCanncelled(String parameters) {
        return parameters.contains("openid.mode=cancel");
    }

    @Override
    public boolean isValidParameters(String parameters, String[] via) throws IOException {
        String body = parameters.replace("openid.mode=id_res", "openid.mode=check_authentication");
        StringBuilder sb = new StringBuilder(endpoint);
        if (endpoint.indexOf('?') < 0) {
            sb.append('?');
        } else {
            sb.append('&');
        }
        sb.append(body);
        HttpEntity entity = client.getEntity(sb.toString(), "text/plain");
        try {
            return EntityUtils.toString(entity).contains("is_valid:true");
        } finally {
            EntityUtils.consume(entity);
        }
    }

    @Override
    public String getUserIdentifier(String parameters) {
        return resolve(getValueAfter(parameters, "&openid.claimed_id="));
    }

    @Override
    public String getUserFullName(String parameters) {
        Map<String, String> values = keyByName(parameters);
        Map<String, String> keys = keyByValue(parameters);
        String name = getAxValue("http://axschema.org/namePerson", keys, values);
        if (name != null)
            return name;
        String firstname = getAxValue("http://axschema.org/namePerson/first", keys, values);
        String lastname = getAxValue("http://axschema.org/namePerson/last", keys, values);
        String email = getAxValue("http://axschema.org/contact/email", keys, values);
        if (firstname != null && lastname != null) {
            return firstname + ' ' + lastname;
        } else if (email != null) {
            return email;
        } else {
            return getUserIdentifier(parameters);
        }
    }

    @Override
    public String getUserLogin(String parameters) {
        Map<String, String> values = keyByName(parameters);
        Map<String, String> keys = keyByValue(parameters);
        String email = getAxValue("http://axschema.org/contact/email", keys, values);
        if (email != null)
            return email;
        return getValueAfter(parameters, "&openid.claimed_id=");
    }

    private String resolve(String reference) {
        if (reference == null)
            return null;
        return tf.resolve(reference);
    }

    private String getAxValue(String type, Map<String, String> keys, Map<String, String> values) {
        String alias = keys.get(type);
        if (alias == null)
            return null;
        return values.get(alias.replace(".type.", ".value."));
    }

    private Map<String, String> keyByName(String cookie) {
        Map<String, String> map = new LinkedHashMap<String, String>();
        for (String pair : cookie.split("&")) {
            int idx = pair.indexOf('=');
            if (idx > 0) {
                String name = decode(pair.substring(0, idx));
                String value = decode(pair.substring(idx + 1));
                map.put(name, value);
            }
        }
        return map;
    }

    private Map<String, String> keyByValue(String cookie) {
        Map<String, String> map = new LinkedHashMap<String, String>();
        for (String pair : cookie.split("&")) {
            int idx = pair.indexOf('=');
            if (idx > 0) {
                String name = decode(pair.substring(0, idx));
                String value = decode(pair.substring(idx + 1));
                map.put(value, name);
            }
        }
        return map;
    }

    private String getValueAfter(String cookie, String token) {
        if (cookie == null)
            return null;
        int idx = cookie.indexOf(token);
        if (idx < 0)
            return null;
        int start = idx + token.length();
        int end = cookie.indexOf('&', start);
        if (end < 0) {
            end = cookie.length();
        }
        return decode(cookie.substring(start, end));
    }

}