在 Spring Security 反应运行时以编程方式选择 Oauth2 身份提供者

问题描述 投票:0回答:1

我有一个反应式 Spring Boot 2 应用程序,它充当使用 Spring Security 启动用户身份验证的 Web 代理。访问此应用程序的最终用户来自公共或私有域,Web 代理应相应地将他们重定向到 Identity-Provider.com(公共)或 Identity-Provider.biz(私有)进行登录。 在两种情况下,redirect_uri 身份验证后保持相同。

我们在 application.yaml 中配置了 2 个 Oauth2 身份提供商和 2 个相应的 Oauth2 客户端。

spring:
  security:
    oauth2:
      client:
        provider:
          idpcom:
            issuer-uri: https://identity-provider.com
          idpbiz:
            issuer-uri: https://identity-provider.biz
        
        registration:
          idpcom:
            provider: idpcom
            client-id: clientid
            client-secret: clientsecret
            authorization-grant-type: authorization_code
            redirect-uri: https://my-domain.com/login/oauth2/code/idpcom
            scope:
              - openid

          idpbiz:
            provider: idpbiz
            client-id: clientid
            client-secret: clientsecret
            authorization-grant-type: authorization_code
            redirect-uri: https://my-domain.com/login/oauth2/code/idpbiz
            scope:
              - openid

通过此配置,当应用程序收到请求时,最终用户会看到两个身份提供商的链接。用户被迫选择其中之一并启动身份验证流程。 what end user sees

我们发现 Spring security 中的以下代码正在构建上面所示的 HTML 页面

ServerHttpSecurity.setDefaultEntryPoints(ServerHttpSecurity http)

我们的要求是在运行时以编程方式解析身份提供者,并直接向最终用户显示相应的登录页面。使用identity-provider.com或identity-provider.biz的决定基于最终用户的IP地址(在X-Forwarded-For标头中捕获)。

我们需要建议来实现此功能。

spring-security oauth-2.0 spring-webflux oauth2client
1个回答
0
投票

根据手册,定义时

http.oauth2Login(oauth2 -> {
    oauth2.loginPage("/login/oauth2");
});

您需要提供一个

@Controller
以及能够呈现自定义登录页面的
@RequestMapping("/login/oauth2") 

你可以写这样的东西:

@Controller
public class LoginController {

    private final Pattern internalIpsPattern;
    
    public LoginController (@Value("internal-ips-pattern") String pattern) {
        this.internalIpsPattern = Pattern.compile(pattern);
    }
    
    @GetMapping("/login/oauth2")
    public RedirectView getAuthorizationCodeInitiationUrl(HttpServletRequest request) {
        final var header = Optional.ofNullable(request.getHeader("X-Forwarded-For")).orElseThrow(() -> new MissingForwardedForException());
        final var matcher = internalIpsPattern.matcher(header);
        return matcher.matches() ? new RedirectView("/oauth2/authorization/idpbiz") : new RedirectView("/oauth2/authorization/idpcom");
    }
    
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    static final class MissingForwardedForException extends RuntimeException {
        private static final long serialVersionUID = 8215954933514492489L;

        MissingForwardedForException() {
        super("X-Forwarded-For header is missing");
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.