biz.neustar.nexus.plugins.gitlab.GitlabAuthenticatingRealm.java Source code

Java tutorial

Introduction

Here is the source code for biz.neustar.nexus.plugins.gitlab.GitlabAuthenticatingRealm.java

Source

/*
 * Copyright (c) 2013 Neustar, Inc. All rights reserved.
 *
 * This program is licensed to you under the Apache License Version 2.0,
 * and you may not use this file except in compliance with the Apache License Version 2.0.
 * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Apache License Version 2.0 is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
 */
package biz.neustar.nexus.plugins.gitlab;

import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang.StringUtils;
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.authc.UsernamePasswordToken;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.security.usermanagement.User;
import org.sonatype.security.usermanagement.UserStatus;

import biz.neustar.nexus.plugins.gitlab.client.GitlabDao;
import biz.neustar.nexus.plugins.gitlab.client.rest.GitlabUser;

@Component(role = Realm.class, hint = GitlabAuthenticatingRealm.ROLE, description = "Gitlab Token Authentication Realm")
public class GitlabAuthenticatingRealm extends AuthorizingRealm implements Initializable, Disposable {

    public static final String GITLAB_MSG = "[Gitlab] ";
    public static final String ROLE = "NexusGitlabAuthenticationRealm";
    private static final String DEFAULT_MESSAGE = "Could not retrieve info from Gitlab.";
    private static final String DISABLED_USER_MESSAGE = "User is disabled in Gitlab.";
    private static AtomicBoolean active = new AtomicBoolean(false);

    @Requirement
    private GitlabDao gitlab;

    private final static Logger LOGGER = LoggerFactory.getLogger(GitlabAuthenticatingRealm.class);

    // testing only.
    static boolean isActive() {
        return active.get();
    }

    @Override
    public void dispose() {
        active.set(false);
        LOGGER.info(GITLAB_MSG + "Realm deactivated.");
    }

    @Override
    public String getName() {
        return GitlabAuthenticatingRealm.class.getName();
    }

    @Override
    public void initialize() throws InitializationException {
        LOGGER.info(GITLAB_MSG + "Realm activated.");
        active.set(true);
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {

        if (!(authenticationToken instanceof UsernamePasswordToken)) {
            throw new UnsupportedTokenException("Token of type " + authenticationToken.getClass().getName()
                    + " is not supported.  A " + UsernamePasswordToken.class.getName() + " is required.");
        }
        UsernamePasswordToken userPass = (UsernamePasswordToken) authenticationToken;
        String token = new String(userPass.getPassword());
        String username = userPass.getUsername();

        if (token.isEmpty()) {
            LOGGER.debug(GITLAB_MSG + "token for {} is empty", username);
            return null;
        }

        try {
            LOGGER.debug(GITLAB_MSG + "authenticating {}", username);

            LOGGER.debug(GITLAB_MSG + "null? " + (gitlab == null));
            LOGGER.debug(GITLAB_MSG + "null? " + (gitlab.getRestClient() == null));

            GitlabUser gitlabUser = gitlab.getRestClient().getUser(username, token);
            User user = gitlabUser.toUser();
            if (user.getStatus() != UserStatus.active) {
                LOGGER.debug(GITLAB_MSG + "authentication failed {}", user);
                throw new AuthenticationException(DISABLED_USER_MESSAGE + " for " + username);
            }
            if (user.getUserId() == null || user.getUserId().isEmpty()) {
                LOGGER.debug(GITLAB_MSG + "authentication failed {}", user);
                throw new AuthenticationException(DEFAULT_MESSAGE + " for " + username);
            }
            LOGGER.debug(GITLAB_MSG + "successfully authenticated {}", username);
            return new SimpleAuthenticationInfo(gitlabUser, userPass.getCredentials(), getName());
        } catch (Exception e) {
            LOGGER.debug(GITLAB_MSG + "authentication failed {}", username);
            throw new AuthenticationException(DEFAULT_MESSAGE, e);
        }
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // only authorize users from this realm
        if (principals.getRealmNames().contains(this.getName())) {
            GitlabUser user = (GitlabUser) principals.getPrimaryPrincipal();
            LOGGER.debug(GITLAB_MSG + "authorizing {}", user.getUsername());
            Set<String> groups = gitlab.getGitlabPluginConfiguration().getDefaultRoles();
            if (user.isActive()) {
                groups.addAll(gitlab.getGitlabPluginConfiguration().getAdminRoles());
            }
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug(GITLAB_MSG + "User: " + user.getUsername() + " gitlab authorization to groups: "
                        + StringUtils.join(groups.iterator(), ", "));
            }
            return new SimpleAuthorizationInfo(groups);
        }
        return null;
    }
}