com.netflix.genie.web.security.saml.SAMLUserDetailsServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.genie.web.security.saml.SAMLUserDetailsServiceImpl.java

Source

/*
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     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 com.netflix.genie.web.security.saml;

import com.google.common.collect.Lists;
import com.netflix.spectator.api.Registry;
import com.netflix.spectator.api.Timer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.saml.SAMLCredential;
import org.springframework.security.saml.userdetails.SAMLUserDetailsService;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Get the user and roles from a SAML certificate.
 *
 * @author tgianos
 * @since 3.0.0
 */
@ConditionalOnProperty("genie.security.saml.enabled")
@Component
@Slf4j
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {

    private static final GrantedAuthority USER = new SimpleGrantedAuthority("ROLE_USER");
    private static final GrantedAuthority ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN");

    private final SAMLProperties samlProperties;
    private final Timer loadTimer;

    /**
     * Constructor.
     *
     * @param samlProperties The SAML properties to use
     * @param registry       The metrics registry to use
     */
    @Autowired
    public SAMLUserDetailsServiceImpl(@NotNull final SAMLProperties samlProperties,
            @NotNull final Registry registry) {
        this.samlProperties = samlProperties;
        this.loadTimer = registry.timer("genie.security.saml.parse.timer");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object loadUserBySAML(final SAMLCredential credential) throws UsernameNotFoundException {
        final long start = System.nanoTime();
        try {
            if (credential == null) {
                throw new UsernameNotFoundException("No credential entered. Unable to get username.");
            }

            final String userAttributeName = this.samlProperties.getAttributes().getUser().getName();
            final String userId = credential.getAttributeAsString(userAttributeName);
            if (StringUtils.isBlank(userId)) {
                throw new UsernameNotFoundException("No user id found using attribute: " + userAttributeName);
            }

            // User exists. Give them at least USER role
            final List<GrantedAuthority> authorities = Lists.newArrayList(USER);

            // See if we can get any other roles
            final String groupAttributeName = this.samlProperties.getAttributes().getGroups().getName();
            final String adminGroup = this.samlProperties.getAttributes().getGroups().getAdmin();
            final String[] groups = credential.getAttributeAsStringArray(groupAttributeName);
            if (groups == null) {
                log.warn("No groups found. User will only get ROLE_USER by default.");
            } else if (Arrays.asList(groups).contains(adminGroup)) {
                authorities.add(ADMIN);
            }

            // For debugging what's available in the credential from the IDP
            if (log.isDebugEnabled()) {
                log.debug("Attributes:");
                credential.getAttributes().forEach(attribute -> {
                    log.debug("Attribute: {}", attribute.getName());
                    log.debug("Values: {}",
                            StringUtils.join(credential.getAttributeAsStringArray(attribute.getName()), ','));
                });
            }

            log.info("{} is logged in with authorities {}", userId, authorities);
            return new User(userId, "DUMMY", authorities);
        } finally {
            final long finished = System.nanoTime();
            this.loadTimer.record(finished - start, TimeUnit.NANOSECONDS);
        }
    }
}