如何验证JWT签名?

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

how to verify JWT signature?

问题

我想用Go AppEngine后端验证Android用户,

我可以通过按照http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html在Android中轻松获取ID令牌

可以使用https://code.google.com/p/google-api-go-client/库的oauth2/v2包验证ID令牌有效载荷。

在使用AppEngine时需要进行一些安装调整,我在http://golangtutorials.blogspot.co.il/2011/11/using-external-api-in-go-appengine.html找到了一些指针

根据文档:“验证签名
事实证明,这是使用Google的公共/私有密钥对进行签名的,并且Google在www.googleapis.com/oauth2/v1/certs上发布公共密钥(我们定期更改);请随意查看。

您必须验证ID令牌(实际上是JSON Web令牌)是否使用其中一个证书进行了签名。幸运的是,有一些不错的库可以做到这一点;在本文中,我将为Java,Ruby和PHP提供指针。

这些库可以缓存Google证书,并且仅在需要时刷新它们,因此验证(几乎总是)是一个快速的静态调用。”

如何在Go中验证令牌是否由Google签名?

英文:

I want to authenticate Android users with a Go AppEngine backend,

I can easily get an ID-token in Android by following http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html

the ID-token payload can be verified with the oauth2/v2 package of the https://code.google.com/p/google-api-go-client/ library.

some installation tweaks are necessary for using it with AppEngine, I found some pointers at http://golangtutorials.blogspot.co.il/2011/11/using-external-api-in-go-appengine.html

according to the doc: "Verify Signature
It turns out that this is signed using a Google public/private key pair, and Google publishes the public keys (which we change regularly) at www.googleapis.com/oauth2/v1/certs; go ahead and have a look.

You have to verify that the ID Token, which is actually a JSON Web Token, was signed with one of those certs. Fortunately, there are decent libraries around to do this; in this post, I’ll give pointers for Java, Ruby, and PHP.

The libraries can cache the Google certs and only refresh them when required, so the verification is (almost always) a fast static call."

how do I verify in Go that the token was signed by Google?

答案1

得分: 2

这是我最终使用的代码(使用https://github.com/dgrijalva/jwt-go):

package XXX

import (
	"errors"
	oauth2 "code.google.com/p/google-api-go-client/oauth2/v2"
	"jwt"
	"appengine"
	"appengine/urlfetch"
)

func getTokeninfo(c appengine.Context, token string) (*oauth2.Tokeninfo, error) {
	client := urlfetch.Client(c)

	oauth2Svc, err := oauth2.New(client) 

	if err != nil {
		return nil, err
	}

	return oauth2Svc.Tokeninfo().Id_token(token).Do()
}

func verifyToken(c appengine.Context, token string) (string, error) {
	parsedToken, err := jwt.Parse(token)

	if err != nil {
		c.Debugf(err.Error())
		return "", err
	}

	if parsedToken.Claims["aud"] != "XXX.apps.googleusercontent.com" {
		c.Debugf("aud mismatch")
		return "", errors.New("Aud mismatch")
	}

	if (parsedToken.Claims["azp"] != "XXX.apps.googleusercontent.com") && 
		(parsedToken.Claims["azp"] != "XXX.apps.googleusercontent.com") {

		c.Debugf("azp mismatch")
		return "", errors.New("Azp mismatch")
	}

	ti, err := getTokeninfo(c, token)

	if err != nil {
		c.Debugf(err.Error())
		return "", err
	}

	if (ti.Issued_to != "XXX.apps.googleusercontent.com") &&
		(ti.Issued_to != "XXX.apps.googleusercontent.com") {

		c.Debugf("cid mismatch")
		return "", errors.New("Client ID mismatch")
	}

	return ti.User_id, nil
}
英文:

this is what I ended up doing (using https://github.com/dgrijalva/jwt-go):

package XXX
import (
"errors"
oauth2 "code.google.com/p/google-api-go-client/oauth2/v2"
"jwt"
"appengine"
"appengine/urlfetch"
)
func getTokeninfo(c appengine.Context, token string) (*oauth2.Tokeninfo, error) {
client := urlfetch.Client(c)
oauth2Svc, err := oauth2.New(client) 
if err != nil {
return nil, err
}
return oauth2Svc.Tokeninfo().Id_token(token).Do()
}
func verifyToken(c appengine.Context, token string) (string, error) {
parsedToken, err := jwt.Parse(token)
if err != nil {
c.Debugf(err.Error())
return "", err
}
if parsedToken.Claims["aud"] != "XXX.apps.googleusercontent.com" {
c.Debugf("aud mismatch")
return "", errors.New("Aud mismatch")
}
if (parsedToken.Claims["azp"] != "XXX.apps.googleusercontent.com") && 
(parsedToken.Claims["azp"] != "XXX.apps.googleusercontent.com") {
c.Debugf("azp mismatch")
return "", errors.New("Azp mismatch")
}
ti, err := getTokeninfo(c, token)
if err != nil {
c.Debugf(err.Error())
return "", err
}
if (ti.Issued_to != "XXX.apps.googleusercontent.com") &&
(ti.Issued_to != "XXX.apps.googleusercontent.com") {
c.Debugf("cid mismatch")
return "", errors.New("Client ID mismatch")
}
return ti.User_id, nil
}

答案2

得分: 1

你可能想看一下https://github.com/someone1/gcp-jwt-go上的appengine签名扩展。

英文:

You might want to look at the appengine signing extension at https://github.com/someone1/gcp-jwt-go

huangapple
  • 本文由 发表于 2013年4月24日 16:51:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/16187548.html
匿名

发表评论

匿名网友

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

确定