概述

这里记录了,接入AppleID登录,服务端的实现。

针对后端验证苹果提供了两种验证方式:

  • 一种是 基于JWT的算法验证
  • 一种是 基于授权码的验证

identityToken是一个经过签名的JSON Web Token的方式实现,更多见Sign in with Apple REST API。 另一种方式是校验授权码,其主要分为两步:1. 用户授权后获取code;2. 通过code换取token。

服务端验证identityToken时,App客户端需要将苹果接口返回的identityToken, userID这两个参数传递给服务器,用于验证本次登录的有效性。

服务端,获取到Apple公钥,来验证identityToken的有效性。

公钥获取接口:https://appleid.apple.com/auth/keys , 文档见Fetch Apple’s Public Key for Verifying Token Signature

实现

代码在GitHub

实现1,主要使用github.com/dgrijalva/jwt-go 和 github.com/lestrrat-go/jwx/jwk

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func VerfiyToken(token string) error {
	_, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
		set, err := jwk.Fetch(context.Background(), "https://appleid.apple.com/auth/keys")
		if err != nil {
			return nil, err
		}

		kid := t.Header["kid"]
		if key, ok := set.LookupKeyID(fmt.Sprint(kid)); ok {
			if _, ok := t.Method.(*jwt.SigningMethodRSA); !ok {
				return nil, fmt.Errorf("unexpected signing method: %s", t.Header["alg"])
			}

			var rawKey interface{}
			if err = key.Raw(&rawKey); err != nil {
				return nil, err
			}

			return rawKey, nil
		}

		return nil, nil
	})

	return err
}

实现2 github.com/lestrrat-go/jwx/jwk

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
func VerifyToken2(payload string) error {
	set, err := jwk.Fetch(context.Background(), "https://appleid.apple.com/auth/keys")
	if err != nil {
		return err
	}

	token, err := ljwt.Parse([]byte(payload), ljwt.WithKeySet(set), ljwt.UseDefaultKey(true))
	if err != nil {
		return err
	}

	fmt.Println(token)
	return nil
}