oauth2流

uklbhaso  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(572)

我目前正在使用springbootweb和oauth2在aws上使用amazoncognito构建一个web应用程序。
我的目标设置如下所示:

在“我的数据中心”中,我运行了两个应用程序:
网关应用程序
后端应用程序
网关应用程序可以从internet访问。它服务于前端(html、css、js),包含一些显示逻辑,也许还有一些api,每个人都可以访问。它是“授权码授予”OAuth2.0流的发起程序(如果用户还没有登录,它会将用户重定向到AmazonCognito)。
后端应用程序只能由网关应用程序访问。不能从外面接近。在后端应用程序中,我想从amazoncognito检索用户详细信息(姓名、电子邮件)。

我现在要做的是:

我在amazoncognito中为网关应用程序注册了一个客户机。网关应用程序启动“授权码授予”流,并可以从amazoncognito访问用户信息。
我将网关应用程序配置为将oauth2授权详细信息与所有http请求一起传递给后端应用程序。后端应用程序可以成功地检查用户是否经过身份验证。

网关应用程序配置

应用程序.yml

spring:
  security:
    oauth2:
      client:
        registration:
          cognito:
            client-name: frontend-local
            client-id: #######
            client-secret: #########
            scope: openid,backend/read,backend/write
            redirect-uri: http://localhost:8080/login/oauth2/code/cognito
        provider:
          cognito:
            issuer-uri: https://cognito-idp.eu-central-1.amazonaws.com/<my-aws-pool-id>
            user-name-attribute: cognito:username

安全配置.java

package io.share.frontend.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf()
                .and()
                .authorizeRequests().antMatchers("/", "/webjars/**").permitAll().anyRequest().authenticated()
                .and()
                .oauth2Login()
                .and()
                .logout().logoutSuccessUrl("/");
    }
}

OAuth2WebClient配置.java

package io.share.frontend.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class OAuth2WebClientConfiguration {

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) {

        OAuth2AuthorizedClientProvider authorizedClientProvider =
                OAuth2AuthorizedClientProviderBuilder.builder()
                        .clientCredentials()
                        .build();

        DefaultOAuth2AuthorizedClientManager authorizedClientManager =
                new DefaultOAuth2AuthorizedClientManager(
                        clientRegistrationRepository, authorizedClientRepository);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }

    @Bean
    WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
                new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oauth2Client.setDefaultClientRegistrationId("cognito");
        return WebClient.builder()
                .apply(oauth2Client.oauth2Configuration())
                .build();
    }
}

后端应用程序配置

应用程序.yml

server:
  port: 8081

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://cognito-idp.eu-central-1.amazonaws.com/<my-aws-pool-id>

安全配置.java

package io.share.backend.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().anyRequest().hasAuthority("SCOPE_backend/read")
                .and()
                .oauth2ResourceServer().jwt();
    }
}

我想干什么

在我的后端应用程序中,我希望能够从amazoncognito访问用户信息。目前,我的后端应用程序中有以下基本restcontroller:

package io.share.backend.web;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

@RestController
public class ObjectResource {

    @GetMapping("/username")
    public String greeting(@AuthenticationPrincipal Principal user) {
        return user.getName();// this currently returns some UUID-Like string, I want to be able to access the username and E-Mail here, just like I can in the Gateway
    }
}

但我希望能够访问真正的用户名和电子邮件在后端。

我的问题

我必须在amazoncognito中为后端创建一个新的客户机吗?或者我必须为网关和后端配置相同的客户端id和客户端密码吗?
我必须在我的应用程序(网关和后端)中进行哪些额外的spring配置才能使其工作?
我用的是Spring Boot 2.3.6.RELEASE

6mzjoqzu

6mzjoqzu1#

问得好,您在使用API时遇到了以下常见的oauth问题:
cognito访问令牌包含很少的用户信息,这是一个很好的实践——它们不可定制,只包含一个主题声明
spring只想从jwt创建一个authenticatedprincipal,但是您的api还希望向authenticatedprincipal添加其他声明
设计模式
有一个设计模式,你可以使用,或借鉴的想法,我的博客文章总结了行为。其思想是首先定义一个声明主体,然后在运行时用来自多个源的声明填充它。在您的例子中,一个源将是cognito用户信息端点。
工作代码
您可以运行我的示例springbootapi,它也使用awscognito,关键类是authorizer。在某些设置中,您可以使用api网关来为您完成以下工作:
如何运行api
spring boot oauth与自定义声明集成
利弊
此模式将为您提供可扩展的声明,但也会给api增加一些复杂性,因为您需要覆盖api技术堆栈的默认oauth行为。

相关问题