All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.aaa.shiro.realm.TokenAuthRealm Maven / Gradle / Ivy

There is a newer version: 0.20.3
Show newest version
/*
 * Copyright (c) 2015 - 2017 Brocade Communications Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.aaa.shiro.realm;

import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.opendaylight.aaa.api.Authentication;
import org.opendaylight.aaa.api.AuthenticationService;
import org.opendaylight.aaa.api.TokenAuth;
import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal;
import org.opendaylight.aaa.shiro.principal.ODLPrincipalImpl;
import org.opendaylight.aaa.shiro.realm.util.TokenUtils;
import org.opendaylight.aaa.shiro.realm.util.http.header.HeaderUtils;
import org.opendaylight.aaa.tokenauthrealm.auth.TokenAuthenticators;
import org.opendaylight.yangtools.concepts.Registration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TokenAuthRealm is an adapter between the AAA shiro subsystem and the existing {@code TokenAuth} mechanisms. Thus, one
 * can enable use of {@code IDMStore} and {@code IDMMDSALStore}.
 */
public class TokenAuthRealm extends AuthorizingRealm {
    private static final Logger LOG = LoggerFactory.getLogger(TokenAuthRealm.class);
    private static final ThreadLocal AUTHENICATORS_TL = new ThreadLocal<>();
    private static final ThreadLocal AUTH_SERVICE_TL = new ThreadLocal<>();

    private final TokenAuthenticators authenticators;
    private final AuthenticationService authService;

    public TokenAuthRealm() {
        this(verifyLoad(AUTH_SERVICE_TL), verifyLoad(AUTHENICATORS_TL));
    }

    public TokenAuthRealm(final AuthenticationService authService, final TokenAuthenticators authenticators) {
        this.authService = requireNonNull(authService);
        this.authenticators = requireNonNull(authenticators);
        super.setName("TokenAuthRealm");
    }

    public static Registration prepareForLoad(final AuthenticationService authService,
            final TokenAuthenticators authenticators) {
        AUTH_SERVICE_TL.set(requireNonNull(authService));
        AUTHENICATORS_TL.set(requireNonNull(authenticators));
        return () -> {
            AUTH_SERVICE_TL.remove();
            AUTHENICATORS_TL.remove();
        };
    }

    private static  T verifyLoad(final ThreadLocal threadLocal) {
        return verifyNotNull(threadLocal.get(), "TokenAuthRealm loading not prepared");
    }

    /**
     * {@inheritDoc}
     *
     * 

* Roles are derived from {@code TokenAuth.authenticate()}. Shiro roles are identical to existing IDM roles. */ @Override protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principalCollection) { final var primaryPrincipal = principalCollection.getPrimaryPrincipal(); if (primaryPrincipal instanceof ODLPrincipal odlPrincipal) { return new SimpleAuthorizationInfo(odlPrincipal.getRoles()); } LOG.error("Could not decode authorization request: {} is not a known principal type", primaryPrincipal); return new SimpleAuthorizationInfo(); } /** * {@inheritDoc} * *

* Authenticates against any {@code TokenAuth} registered with the {@code ServiceLocator}. */ @Override protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authenticationToken) throws AuthenticationException { if (authenticationToken == null) { throw new AuthenticationException("{\"error\":\"Unable to decode credentials\"}"); } final String username; final String password; final String domain; try { final String possiblyQualifiedUser = TokenUtils.extractUsername(authenticationToken); username = HeaderUtils.extractUsername(possiblyQualifiedUser); domain = HeaderUtils.extractDomain(possiblyQualifiedUser); password = TokenUtils.extractPassword(authenticationToken); } catch (ClassCastException e) { throw new AuthenticationException( "{\"error\":\"Only basic authentication is supported by TokenAuthRealm\"}", e); } if (!Strings.isNullOrEmpty(password)) { Map> headers = HeaderUtils.formHeaders(username, password, domain); // iterate over TokenAuth implementations and // attempt to // authentication with each one for (TokenAuth ta : authenticators.getTokenAuthCollection()) { try { LOG.debug("Authentication attempt using {}", ta.getClass().getName()); final Authentication auth = ta.validate(headers); if (auth != null) { LOG.debug("Authentication attempt successful"); authService.set(auth); final ODLPrincipal odlPrincipal = ODLPrincipalImpl.createODLPrincipal(auth); return new SimpleAuthenticationInfo(odlPrincipal, password.toCharArray(), getName()); } } catch (AuthenticationException ae) { LOG.debug("Authentication attempt unsuccessful", ae); // Purposefully generic message throw new AuthenticationException("{\"error\":\"Could not authenticate\"}", ae); } } } LOG.debug("Authentication failed: exhausted TokenAuth resources"); return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy