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

com.cloudimpl.outstack.spring.security.PlatformAuthenticationManager Maven / Gradle / Ivy

There is a newer version: 4.0.551
Show newest version
/*
 * Copyright 2021 nuwan.
 *
 * 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.cloudimpl.outstack.spring.security;

import com.cloudimpl.outstack.runtime.ValidationErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import reactor.core.publisher.Mono;

/**
 *
 * @author nuwan
 */
public abstract class PlatformAuthenticationManager implements ReactiveAuthenticationManager {

    private final AuthenticationProvider authenticationProvider;
    
    private final AuthorizationProvider authorizationProvider;
    
    private final TokenProvider tokenProvider;

    public PlatformAuthenticationManager(@Autowired(required = false) AuthenticationProvider authenticationProvider,@Autowired(required = false) AuthorizationProvider authorizationProvider,@Autowired(required = false) TokenProvider tokenProvider) {
        this.authenticationProvider = authenticationProvider == null ? t->Mono.error(()->new RuntimeException("AuthenticationProvider not provisioned")): authenticationProvider;
        this.authorizationProvider = authorizationProvider == null ? t->Mono.error(()->new PlatformAuthenticationException("AuthorizationProvider not provisioned",null)): authorizationProvider;
        this.tokenProvider = tokenProvider == null ? t->Mono.error(()->new PlatformAuthenticationException("TokenProvider not provisioned",null)): tokenProvider;
    }
  
    @Override
    public Mono authenticate(Authentication authentication) {
        return convertToPlatformToken(authentication).doOnNext(pt->pt.setSystemToken(authentication)).flatMap(this::onPlatformToken).cast(Authentication.class);
    }

    private Mono onPlatformToken(PlatformAuthenticationToken token) {
        AuthenticationMeta meta = token.getAuthMeta();
        if (meta == null) {
            throw new PlatformAuthenticationException("no meta data found in the platform token", null);
        }
        switch (meta.getTokenFlow()) {
            case AUTHENTICATION_FLOW: {
                return authenticationProvider.authenticate(token);
            }
            case AUTHORIZATION_FLOW: {
                return authorizationProvider.authenticate(token);
            }
            case TOKEN_FLOW: {
                return Mono.just(token).doOnNext(t->validateTokenFlow(t)).flatMap(t->tokenProvider.authenticate(t)).doOnNext(this::validateTokenResponse);
            }
            default: {
                return Mono.error(() -> new PlatformAuthenticationException("unknown token flow:" + meta.getTokenFlow(), null));
            }
        }
    }

    protected abstract Mono convertToPlatformToken(Authentication autentication);

    
    private void validateTokenResponse(PlatformAuthenticationToken token)
    {
        if(token.getResponse() == null || !(token.getResponse() instanceof TokenResponse))
        {
            throw new PlatformAuthenticationException("token response is null or invalid", null);
        }
    }
    
    private void validateTokenFlow(PlatformAuthenticationToken token)
    {
        switch(token.getAuthMeta().getGrantType())
        {
            case AUTHORIZATION_CODE:
            {
                break;
            }
            case PASSWORD:
            {
                if(!UsernamePasswordAuthenticationToken.class.isInstance(token.getSystemToken()))
                {
                    throw new ValidationErrorException("grant type does not match with token type");
                }
                break;
            }
            case REFRESH_TOKEN:
            {
                if(!BearerTokenAuthenticationToken.class.isInstance(token.getSystemToken()))
                {
                    throw new ValidationErrorException("grant type does not match with token type");
                }
                break;
            }
            case CUSTOM_TOKEN:
            {
                if(!BearerTokenAuthenticationToken.class.isInstance(token.getSystemToken()))
                {
                    throw new ValidationErrorException("grant type does not match with token type");
                }
                break;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy