使用 Grails 实现 OAuth2 提供程序

Posted

技术标签:

【中文标题】使用 Grails 实现 OAuth2 提供程序【英文标题】:implementing an OAuth2 provider with Grails 【发布时间】:2015-05-07 03:47:42 【问题描述】:

我正在尝试使用 Spring Security OAuth2 Provider 插件实现一个提供 OAuth2 的 Grails 应用程序。 The provider app 和我用来测试它的 client app 都可以在 GitHub 上找到。

我遵循了instructions in the plugin's docs,它解释了如何实现提供程序。为了测试它,我将以下 oauth 客户端和用户保存在 Bootstrap.groovy

def init =  servletContext ->

    def saveArgs = [flush: true, failOnError: true]

    def userRole = new Role(authority: 'ROLE_USER').save(saveArgs)
    def clientRole = new Role(authority: 'ROLE_CLIENT').save(saveArgs)

    // create an OAuth client
    new Client(
            clientId: 'my-client',
            authorizedGrantTypes: ['authorization_code', 'refresh_token', 'implicit', 'password', 'client_credentials'],
            authorities: ['ROLE_CLIENT'],
            scopes: ['read', 'write'],
            redirectUris: ['http://localhost:9090/oauth-client/auth/callback']
    ).save(saveArgs)

    // create a regular user
    def user = new User(username: 'me', password: 'password').save(saveArgs)
    UserRole.create user, userRole, true

在客户端应用程序中,我单击以下链接以启动授权代码授予流程

<g:set var="redirectUrl" value="$g.createLink(controller: 'auth', action: 'callback', absolute: true)"/>
<h2>
    <a href="http://localhost:8080/oauth2-provider/oauth/authorize?response_type=code&client_id=my-client&scope=read&redirect_uri=$redirectUrl">OAuth Login</a>
</h2>

我在登录表单中输入上述用户的用户名和密码,然后单击确认对话框中显示的“授权”按钮。授权码已成功返回给客户端应用,但当它尝试将其交换为访问令牌时,会出现以下错误

invalid_scope:空范围(无论是客户端还是用户都不允许请求的范围)

用于交换访问令牌的授权码的代码如下所示。

String getAccessToken(String authCode) 

    def url = 'http://localhost:8080/oauth2-provider/oauth/token'

    def params = [
            grant_type: 'authorization_code',
            code: authCode,
            client_id: 'my-client'
    ]

    new HTTPBuilder(url).request(POST, JSON) 
        uri.query = params

        response.success =  resp, json ->
            json.access_token
        

        response.failure =  resp, json ->
            log.error "HTTP error code: $resp.status, status line: $resp.statusLine, "

            json.each  key, value ->
                log.error "$key: $value"
            
        
    

启动 OAuth 流程的链接请求访问 read 范围。此包含在Client 对象的scopes 属性中,因此没有明显的理由禁止访问此范围。

您可以按照以下说明重现错误:

使用grails run-app 启动提供程序应用程序 使用grails run-app -Dserver.port=9090 在端口 9090 上启动客户端应用程序 在客户端应用程序的主页上单击“OAuth 登录”链接。这将重定向到提供商应用程序并提示您登录。输入用户名“me”,密码“password”,然后在随后出现的确认对话框中点击“授权”按钮。

【问题讨论】:

【参考方案1】:

对于将来偶然发现此问题的任何人:

这是插件中一个小错误的结果。临时解决方法是在令牌端点请求中包含范围参数,其值与发送到授权端点的范围参数相同。

有关该问题的更多详细信息,请参阅插件的 GitHub 存储库上的 issue #64。

【讨论】:

以上是关于使用 Grails 实现 OAuth2 提供程序的主要内容,如果未能解决你的问题,请参考以下文章

Grails 中的 Spring Oauth2 提供程序 - 依赖项

Grails spring security oauth2 提供者对具有正确承载令牌的资源的请求重定向到登录

如何绕过 Grails 异常处理以使用 Spring Oauth2?

Grails OAuth2 登录密码凭据授予返回 invalid_client

Grails 和 Spring Security & Facebook & Oauth2 - Restful 服务器

Grails oAuth2 Provider 插件不对 grant_type 'password' 进行身份验证