org.forgerock.openidm.jaspi.modules.PassthroughAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for org.forgerock.openidm.jaspi.modules.PassthroughAuthenticator.java

Source

/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions copyright [year] [name of copyright owner]".
 *
 * Copyright 2013 ForgeRock Inc.
 */

package org.forgerock.openidm.jaspi.modules;

import org.apache.commons.lang3.StringUtils;
import org.forgerock.json.fluent.JsonValue;
import org.forgerock.json.resource.JsonResource;
import org.forgerock.json.resource.JsonResourceAccessor;
import org.forgerock.json.resource.JsonResourceContext;
import org.forgerock.json.resource.JsonResourceException;
import org.forgerock.openidm.core.ServerConstants;
import org.forgerock.openidm.http.ContextRegistrator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.security.auth.message.AuthException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * Contains logic to perform authentication by passing the request through to be authenticated against a OpenICF
 * connector.
 *
 * @author Phill Cunnington
 */
public class PassthroughAuthenticator {

    final static Logger logger = LoggerFactory.getLogger(PassthroughAuthenticator.class);

    private final String passThroughAuth;
    private final JsonValue propertyMapping;
    private final List<String> defaultRoles;

    /**
     * Constructs an instance of the PassthroughAuthenticator.
     *
     * @param passThroughAuth The passThroughAuth resource.
     * @param userRolesProperty The user roles property.
     * @param defaultRoles The list of default roles.
     */
    public PassthroughAuthenticator(String passThroughAuth, JsonValue propertyMapping, List<String> defaultRoles) {
        this.passThroughAuth = passThroughAuth;
        this.propertyMapping = propertyMapping;
        this.defaultRoles = defaultRoles;
    }

    /**
     * Performs the ICF Passthrough authentication.
     *
     * @param authData The AuthData object.
     * @param password The user's password.
     * @return The AuthData object the was passed in, with information set on it from the results of the authentication
     * request.
     * @throws AuthException If pass-through authentication fails.
     */
    public boolean authenticate(AuthData authData, String password) throws AuthException {

        String userRolesProperty = propertyMapping.get("userRoles").asString();

        if (!StringUtils.isEmpty(passThroughAuth) && !"anonymous".equals(authData.getUsername())) {
            JsonResource router = getJsonResource();
            if (null != router) {
                JsonResourceAccessor accessor = new JsonResourceAccessor(router,
                        JsonResourceContext.getContext(JsonResourceContext.newRootContext(), "resource"));

                JsonValue params = new JsonValue(new HashMap<String, Object>());
                params.put(ServerConstants.ACTION_NAME, "authenticate");
                params.put("username", authData.getUsername());
                params.put("password", password);
                try {
                    JsonValue result = accessor.action(passThroughAuth, params, null);
                    boolean authenticated = result.isDefined(ServerConstants.OBJECT_PROPERTY_ID);
                    if (authenticated) {
                        authData.setResource(passThroughAuth);
                        authData.setUserId(result.get(ServerConstants.OBJECT_PROPERTY_ID).required().asString());

                        result = accessor.read(passThroughAuth + "/" + authData.getUserId());

                        if (userRolesProperty != null && result.isDefined(userRolesProperty)) {
                            authData.setRoles((List) result.get(userRolesProperty).getObject());
                        } else if (authData.getRoles().size() == 0) {
                            authData.getRoles().addAll(defaultRoles);
                        }

                        return true;
                    }
                } catch (JsonResourceException e) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Failed pass-through authentication of {} on {}.", authData.getUsername(),
                                passThroughAuth, e);
                    }
                    if (e.isServerError()) {
                        throw new AuthException("Failed pass-through authentication of " + authData.getUsername()
                                + " on " + passThroughAuth + ".");
                    }
                    //authentication failed
                    return false;
                }
            }
        }

        return false;
    }

    /**
     * Gets the Json Resource.
     *
     * @return The JsonResource.
     */
    private JsonResource getJsonResource() {
        // TODO: switch to service trackers
        BundleContext ctx = ContextRegistrator.getBundleContext();
        Collection<ServiceReference<JsonResource>> routers = null;
        try {
            routers = ctx.getServiceReferences(JsonResource.class, "(openidm.restlet.path=/)");
        } catch (InvalidSyntaxException e) {
            /* ignore, the filter is tested */
        }
        if (ctx != null) {
            return routers.size() > 0 ? ctx.getService(routers.iterator().next()) : null;
        } else {
            return null;
        }
    }
}