在OAuth2中,何时随机化授权代码/状态?

huangapple go评论69阅读模式
英文:

When to randomize auth code/state in oauth2?

问题

根据 https://www.godoc.org/golang.org/x/oauth2#Config.AuthCodeURL 的文档:

...State 是用来保护用户免受 CSRF 攻击的令牌。你必须始终提供一个非零的字符串...

以及 https://www.rfc-editor.org/rfc/rfc6749#section-10.12

...任何发送到重定向 URI 终点的请求都必须包含一个绑定请求的值...

然而,这仅适用于在流程的某个部分没有会话数据时,即用户尚未登录且授权码仅在显示匿名页面时生成。

那么,在回调时如何随机生成并比较这个值呢?它是一个每个服务器都随机生成的静态值吗?

英文:

According to the docs at https://www.godoc.org/golang.org/x/oauth2#Config.AuthCodeURL

> ...State is a token to protect the user from CSRF attacks. You must always provide a non-zero string...

and at https://www.rfc-editor.org/rfc/rfc6749#section-10.12

> ...any request sent to the redirection URI endpoint to include a value that binds the request...

Yet this is specifically at the part in the flow when there is no session data, i.e. the user has not logged in and the auth code is only generated upon showing the anonymous page.

How then can this value be randomized and compared upon callback? Is it a static value randomized per server?

答案1

得分: 3

您可以使用state参数来标识授权服务器的回调与发送的请求是否匹配。如果没有state参数,攻击者可以使用随机访问令牌调用您的回调URL,而您并没有请求该令牌。使用state参数,您可以确定所调用的回调是对您发出的请求的响应。

因此,您可以为每个发送的请求随机生成一个state值,并在接收到匹配的回调之前跟踪它。它可以是任何您想要的内容,只要无法猜测即可。

一个简单的方法是利用rand.Reader函数生成随机字节,并对结果进行Base64编码:

func state(n int) (string, error) {
    data := make([]byte, n)
    if _, err := io.ReadFull(rand.Reader, data); err != nil {
        return "", err
    }
    return base64.StdEncoding.EncodeToString(data), nil
}

这个函数会返回一个指定长度的随机字符串作为state值,并且可以防止跨站请求伪造攻击。

英文:

> state
>
> RECOMMENDED. An opaque value used by the client to maintain
> state between the request and callback. The authorization
> server includes this value when redirecting the user-agent back
> to the client. The parameter SHOULD be used for preventing
> cross-site request forgery as described in Section 10.12.

> RFC 6749

You use state to identify that the callback from the authorization server matches the request sent. If there wasn't state a attacker could just call your callback url with a random access token that you didn't request. With state you know that the called callback is in response to the request you made.

So you randomize state per request that you sent and track it until you receive the matching callback. It can be anything you want as long as it can't be guessed.

A simple approach would be leveraging rand.Reader and base64 encoding the result:

func state(n int) (string, error) {
	data := make([]byte, n)
	if _, err := io.ReadFull(rand.Reader, data); err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(data), nil
}

huangapple
  • 本文由 发表于 2016年2月22日 23:59:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/35558166.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定