集成 Spring Security OAuth2 和 Spring Social [英] Integrate Spring Security OAuth2 and Spring Social

查看:73
本文介绍了集成 Spring Security OAuth2 和 Spring Social的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Spring Boot + Spring Security OAuth2 应用程序,我相信它的灵感来自 Dave Syer 的示例.该应用程序配置为 OAuth2 授权服务器,具有使用资源所有者密码凭据流的单个公共客户端.成功的令牌被配置为 JWT.

I'm working with a Spring Boot + Spring Security OAuth2 application that I believe was inspired by examples from Dave Syer. The application is configured to be an OAuth2 authorization server, with a single public client using the Resource Owner Password Credentials flow. A successful token is configured to be a JWT.

公共 Angular 客户端向/oauth/token 发送一个 POST 请求,其中包含一个包含客户端 ID 和机密的基本身份验证标头(这是让客户端进行身份验证的最简单方法,即使机密不是私有的).请求正文包含用户名、密码和密码"的授予类型.

The public Angular client sends a POST request to /oauth/token with a basic auth header containing the client id and secret (this was the easiest way to get the client to authenticate, even though the secret is not private). The body of the request contains username, password, and grant type of "password".

除了作为身份验证服务器之外,该应用程序还是面向用户、团队和组织的 RESTful 资源服务器.

In addition to being an authentication server, the application is a RESTful resource server for users, teams, and organizations.

我正在尝试使用 Spring Social 添加额外的 SSO 身份验证流程.我已经将 Spring Social 配置为通过/auth/[provider] 通过外部提供商进行身份验证;但是,以下请求不再正确设置 SecurityContext.可能是 Spring Security OAuth 服务器或客户端覆盖了 SecurityContext?

I'm trying to add an additional SSO authentication flow using Spring Social. I've got Spring Social configured to authenticate through external providers via /auth/[provider]; however, following requests no longer have the SecurityContext correctly set. Possibly, Spring Security OAuth server or client is overriding the SecurityContext?

如果我能在 Spring Social 流程之后正确设置 SecurityContext,我就有了一个新的 TokenGranter,它允许一个新的社交"授予类型,它会检查预认证用户的 SecurityContextHolder.

If I can get the SecurityContext correctly set after the Spring Social flow, I've got a new TokenGranter that allows a new grant type of "social" that would check the SecurityContextHolder for the pre authenticated user.

我对 SecurityContext 的特定问题的解决方案感兴趣(我认为这是 Spring OAuth + Social 集成的问题),或者对外部提供者进行身份验证并从我们自己的身份验证中获取有效 JWT 的不同方法服务器.

I'm interested in both a solution to my specific problem with the SecurityContext (I believe it's an issue with Spring OAuth + Social integration), or a different approach for authenticating with external providers and getting a valid JWT from our own auth server.

谢谢!

推荐答案

我在 JHipster 生成的 Web 应用程序上遇到了类似的问题.最后我决定使用 Spring Social 的 SocialAuthenticationFilter 选项(通过 SpringSocialConfigurer).社交登录成功后,服务器通过重定向到客户端应用程序自动生成并返回自己的"访问令牌.

I had a similar problem on a JHipster-generated web application. Finally I decided to go with the SocialAuthenticationFilter option from Spring Social (via the SpringSocialConfigurer). After a successful social login, the server automatically generates and returns the "own" access token via redirection to the client app.

这是我的尝试:

@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter implements EnvironmentAware {

    //...

    @Inject
    private AuthorizationServerTokenServices authTokenServices;

    @Override
    public void configure(HttpSecurity http) throws Exception {

        SpringSocialConfigurer socialCfg = new SpringSocialConfigurer();
        socialCfg
            .addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() {
                @SuppressWarnings("unchecked")
                public SocialAuthenticationFilter postProcess(SocialAuthenticationFilter filter){
                    filter.setAuthenticationSuccessHandler(
                            new SocialAuthenticationSuccessHandler(
                                    authTokenServices,
                                    YOUR_APP_CLIENT_ID
                            )
                        );
                    return filter;
                }
            });

        http
            //... lots of other configuration ...
            .apply(socialCfg);
    }        
}

还有 SocialAuthenticationSuccessHandler 类:

public class SocialAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    public static final String REDIRECT_PATH_BASE = "/#/login";
    public static final String FIELD_TOKEN = "access_token";
    public static final String FIELD_EXPIRATION_SECS = "expires_in";

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final AuthorizationServerTokenServices authTokenServices;
    private final String localClientId;

    public SocialAuthenticationSuccessHandler(AuthorizationServerTokenServices authTokenServices, String localClientId){
        this.authTokenServices = authTokenServices;
        this.localClientId = localClientId;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication)
                    throws IOException, ServletException {
        log.debug("Social user authenticated: " + authentication.getPrincipal() + ", generating and sending local auth");
        OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(authentication)); //Automatically checks validity
        String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
            .append("?").append(FIELD_TOKEN).append("=")
            .append(encode(oauth2Token.getValue()))
            .append("&").append(FIELD_EXPIRATION_SECS).append("=")
            .append(oauth2Token.getExpiresIn())
            .toString();
        log.debug("Sending redirection to " + redirectUrl);
        response.sendRedirect(redirectUrl);
    }

    private OAuth2Authentication convertAuthentication(Authentication authentication) {
        OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null,
                null, null, null, null);
        return new OAuth2Authentication(request,
                //Other option: new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", authorities)
                new PreAuthenticatedAuthenticationToken(authentication.getPrincipal(), "N/A")
                );
    }

    private String encode(String in){
        String res = in;
        try {
            res = UriUtils.encode(in, GeneralConstants.ENCODING_UTF8);
        } catch(UnsupportedEncodingException e){
            log.error("ERROR: unsupported encoding: " + GeneralConstants.ENCODING_UTF8, e);
        }
        return res;
    }
}

这样,您的客户端应用程序将通过重定向到 /#/login?access_token=my_access_token&expires_in=seconds_to_expiration 来接收您的网络应用程序的访问令牌,只要您设置相应的 REDIRECT_PATH_BASE<SocialAuthenticationSuccessHandler 中的/code>.

This way your client app will receive your web app's access token via redirection to /#/login?access_token=my_access_token&expires_in=seconds_to_expiration, as long as you set the corresponding REDIRECT_PATH_BASE in SocialAuthenticationSuccessHandler.

希望能帮到你.

这篇关于集成 Spring Security OAuth2 和 Spring Social的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆