com.netflix.genie.web.security.oauth2.pingfederate.PingFederateJWTTokenServicesUnitTests.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.genie.web.security.oauth2.pingfederate.PingFederateJWTTokenServicesUnitTests.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.oauth2.pingfederate;

import com.google.common.collect.Sets;
import com.netflix.genie.test.categories.UnitTest;
import com.netflix.spectator.api.Registry;
import com.netflix.spectator.api.Timer;
import org.hamcrest.Matchers;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.mockito.Mockito;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;

import java.util.Collection;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Unit tests for the PingFederateJWTTokenServices class.
 *
 * @author tgianos
 * @since 3.0.0
 */
@Category(UnitTest.class)
public class PingFederateJWTTokenServicesUnitTests {

    private Timer loadAuthenticationTimer;
    private JwtConsumer jwtConsumer;
    private PingFederateJWTTokenServices tokenServices;

    /**
     * Setup for the tests.
     */
    @Before
    public void setup() {
        this.loadAuthenticationTimer = Mockito.mock(Timer.class);
        final Registry registry = Mockito.mock(Registry.class);
        Mockito.when(registry.timer(Mockito.anyString())).thenReturn(this.loadAuthenticationTimer);
        this.jwtConsumer = Mockito.mock(JwtConsumer.class);
        this.tokenServices = new PingFederateJWTTokenServices(this.jwtConsumer, registry);
    }

    /**
     * Make sure we can successfully load an authentication.
     *
     * @throws AuthenticationException On error
     * @throws InvalidTokenException   When the token is invalid
     * @throws InvalidJwtException     On invalid JWT token
     * @throws MalformedClaimException A bad claim
     */
    @Test
    public void canLoadAuthentication()
            throws AuthenticationException, InvalidTokenException, InvalidJwtException, MalformedClaimException {
        final JwtClaims claims = Mockito.mock(JwtClaims.class);
        final String clientId = UUID.randomUUID().toString();
        final String scope1 = "genie_admin";
        final String scope2 = UUID.randomUUID().toString();
        final Set<String> scopes = Sets.newHashSet(scope1, scope2);
        Mockito.when(claims.getClaimValue("client_id", String.class)).thenReturn(clientId);
        Mockito.when(claims.getClaimValue("scope", Collection.class)).thenReturn(scopes);
        Mockito.when(this.jwtConsumer.processToClaims(Mockito.anyString())).thenReturn(claims);

        final OAuth2Authentication authentication = this.tokenServices
                .loadAuthentication(UUID.randomUUID().toString());
        Assert.assertNull(authentication.getUserAuthentication());
        Assert.assertThat(authentication.getPrincipal(), Matchers.is(clientId));

        final Collection<GrantedAuthority> authorities = authentication.getAuthorities();
        Assert.assertThat(authorities.size(), Matchers.is(3));
        Assert.assertTrue(authorities.containsAll(Sets.newHashSet(new SimpleGrantedAuthority("ROLE_ADMIN"),
                new SimpleGrantedAuthority("ROLE_" + scope2.toUpperCase()),
                new SimpleGrantedAuthority("ROLE_USER"))));

        Mockito.verify(this.loadAuthenticationTimer, Mockito.times(1)).record(Mockito.anyLong(),
                Mockito.eq(TimeUnit.NANOSECONDS));
    }

    /**
     * Make sure we can't load authentication if there are no authorities.
     *
     * @throws AuthenticationException On error
     * @throws InvalidTokenException   When the token is invalid
     * @throws InvalidJwtException     On invalid JWT token
     * @throws MalformedClaimException A bad claim
     */
    @Test(expected = InvalidTokenException.class)
    public void cantLoadAuthentication()
            throws AuthenticationException, InvalidTokenException, InvalidJwtException, MalformedClaimException {
        final JwtClaims claims = Mockito.mock(JwtClaims.class);
        final String clientId = UUID.randomUUID().toString();
        final Set<String> scopes = Sets.newHashSet();
        Mockito.when(claims.getClaimValue("client_id", String.class)).thenReturn(clientId);
        Mockito.when(claims.getClaimValue("scope", Collection.class)).thenReturn(scopes);
        Mockito.when(this.jwtConsumer.processToClaims(Mockito.anyString())).thenReturn(claims);

        this.tokenServices.loadAuthentication(UUID.randomUUID().toString());
        Mockito.verify(this.loadAuthenticationTimer, Mockito.times(1)).record(Mockito.anyLong(),
                Mockito.eq(TimeUnit.NANOSECONDS));
    }

    /**
     * Make sure we can't load authentication if an exception is thrown.
     *
     * @throws AuthenticationException On error
     * @throws InvalidTokenException   When the token is invalid
     * @throws InvalidJwtException     On invalid JWT token
     * @throws MalformedClaimException A bad claim
     */
    @Test
    public void cantProcessClaims()
            throws AuthenticationException, InvalidTokenException, InvalidJwtException, MalformedClaimException {
        final JwtClaims claims = Mockito.mock(JwtClaims.class);
        Mockito.when(claims.getClaimValue("client_id", String.class))
                .thenThrow(new MalformedClaimException("bad claim"));
        Mockito.when(this.jwtConsumer.processToClaims(Mockito.anyString()))
                .thenThrow(new InvalidJwtException("bad jwt")).thenReturn(claims);

        try {
            this.tokenServices.loadAuthentication(UUID.randomUUID().toString());
            Assert.fail();
        } catch (final InvalidTokenException e) {
            Mockito.verify(this.jwtConsumer, Mockito.times(1)).processToClaims(Mockito.anyString());
        }

        try {
            this.tokenServices.loadAuthentication(UUID.randomUUID().toString());
            Assert.fail();
        } catch (final InvalidTokenException e) {
            Mockito.verify(this.jwtConsumer, Mockito.times(2)).processToClaims(Mockito.anyString());
        }

        Mockito.verify(this.loadAuthenticationTimer, Mockito.times(2)).record(Mockito.anyLong(),
                Mockito.eq(TimeUnit.NANOSECONDS));
    }

    /**
     * This method shouldn't be supported by this implementation.
     */
    @Test(expected = UnsupportedOperationException.class)
    public void readAccessTokenNotSupported() {
        this.tokenServices.readAccessToken(UUID.randomUUID().toString());
    }
}