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

me.tfeng.playmods.oauth2.OAuth2Component Maven / Gradle / Ivy

/**
 * Copyright 2015 Thomas Feng
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 me.tfeng.playmods.oauth2;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.stereotype.Component;

import me.tfeng.playmods.avro.ApplicationError;
import me.tfeng.playmods.avro.AvroComponent;
import me.tfeng.toolbox.common.ThrowingFunction;
import play.libs.F.Promise;

/**
 * @author Thomas Feng ([email protected])
 */
@Component("play-mods.oauth2.component")
public class OAuth2Component {

  public static boolean isAuthenticationError(Throwable t) {
    if (t instanceof AccessDeniedException
        || t instanceof AuthenticationException
        || t instanceof ClientAuthenticationException
        || t instanceof ClientRegistrationException
        || t instanceof AuthenticationError
        || (t instanceof ApplicationError) && ((ApplicationError) t).getStatus() == HttpStatus.SC_UNAUTHORIZED) {
      return true;
    }

    Throwable cause = t.getCause();
    if (cause != t && cause != null && isAuthenticationError(cause)) {
      return true;
    }

    if (t instanceof InvocationTargetException) {
      Throwable target = ((InvocationTargetException) t).getTargetException();
      if (isAuthenticationError(target)) {
        return true;
      }
    }

    return false;
  }

  @Autowired
  @Qualifier("play-mods.oauth2.authentication-manager")
  private AuthenticationManagerClient authenticationManager;

  @Autowired
  @Qualifier("play-mods.avro.component")
  private AvroComponent avroComponent;

  public  Promise callWithAuthorizationToken(String token,
      ThrowingFunction, E> function) throws E {
    if (token == null) {
      SecurityContextHolder.clearContext();
      return function.apply();
    } else {
      Promise promise = getAuthenticationManager().authenticate(token);
      return promise.flatMap(authentication -> {
        org.springframework.security.oauth2.provider.OAuth2Authentication oauth2Authentication =
            new org.springframework.security.oauth2.provider.OAuth2Authentication(
                getOAuth2Request(authentication.getClient()),
                getAuthentication(authentication.getUser()));
        SecurityContextHolder.getContext().setAuthentication(oauth2Authentication);
        try {
          return function.apply();
        } finally {
          SecurityContextHolder.clearContext();
        }
      });
    }
  }

  public AuthenticationManagerClient getAuthenticationManager() {
    return authenticationManager;
  }

  public  T localClient(Class interfaceClass, Object implementation) {
    Class implementationClass = implementation.getClass();
    return interfaceClass.cast(Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[] { interfaceClass },
        (proxy, method, args) -> {
          if (Promise.class.isAssignableFrom(method.getReturnType())) {
            org.springframework.security.core.Authentication authentication =
                SecurityContextHolder.getContext().getAuthentication();
            return Promise.promise(() -> {
              Method implementationMethod = implementationClass.getMethod(method.getName(), method.getParameterTypes());
              SecurityContextHolder.getContext().setAuthentication(authentication);
              try {
                return implementationMethod.invoke(implementation, args);
              } catch (InvocationTargetException e) {
                throw e.getTargetException();
              } finally {
                SecurityContextHolder.clearContext();
              }
            }, avroComponent.getExecutionContext());
          } else {
            try {
              return method.invoke(implementation, args);
            } catch (InvocationTargetException e) {
              throw e.getTargetException();
            }
          }
        }));
  }

  private UsernamePasswordAuthenticationToken getAuthentication(UserAuthentication user) {
    if (user == null) {
      return null;
    } else {
      List authorities = user.getAuthorities().stream()
          .map(authority -> new SimpleGrantedAuthority(authority.toString()))
          .collect(Collectors.toList());
      return new UsernamePasswordAuthenticationToken(user.getId().toString(), null, authorities);
    }
  }

  private OAuth2Request getOAuth2Request(ClientAuthentication client) {
    List authorities = client.getAuthorities().stream()
        .map(authority -> new SimpleGrantedAuthority(authority.toString()))
        .collect(Collectors.toList());
    Set scopes = client.getScopes().stream().map(scope -> scope.toString()).collect(Collectors.toSet());
    return new OAuth2Request(Collections.emptyMap(), client.getId().toString(), authorities, true, scopes,
        Collections.emptySet(), null, Collections.emptySet(), Collections.emptyMap());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy