疯狂编程网

  • 首页
  • 后端
    • GOLANG
    • PHP
  • 前端
  • 客户端
  • 服务器
  • AIGC
  • 开发工具
  • 代码人生
  • 关于本站
    • 联系我们
    • 免责声明
  1. 首页
  2. 后端
  3. GOLANG
  4. 正文

苹果授权登陆(Sign in with Apple)服务器基于JWT的算法验证(golang)

2023年6月14日 3605点热度 0人点赞 0条评论

APP登录授权完成后,上传userID和identityToken给服务端,服务端进行JWT验证

服务端是用GO语言处理的,下面为GO语言的实现

package appleid

import (
	"crypto/rsa"
	"encoding/base64"
	"encoding/json"
	"errors"
	"github.com/golang-jwt/jwt/v5"
	"io/ioutil"
	"math/big"
	"net/http"
)

type AppleJwtKey struct {
	Kty string `json:"kty"`
	Kid string `json:"kid"`
	Use string `json:"use"`
	Alg string `json:"alg"`
	N   string `json:"n"`
	E   string `json:"e"`
}

type AppleJwtAuthKeys struct {
	Keys []*AppleJwtKey `json:"keys"`
}

type AppleUser struct {
	jwt.RegisteredClaims
}

func ParseJwtIdentityToken(identityToken, aud string) (*AppleUser, error) {

	t, err := jwt.ParseWithClaims(identityToken, &AppleUser{}, func(token *jwt.Token) (interface{}, error) {
		header := token.Header
		kidStr := ""
		if kid, ok := header["kid"]; ok {
			kidStr = kid.(string)
		} else {
			return nil, errors.New("get kid failed")
		}
		//kidStr = "W6WcOKB"
		return GetRSAPublicKey(kidStr), nil
	}, jwt.WithAudience(aud))

	if claims, ok := t.Claims.(*AppleUser); ok && t.Valid {
		return claims, nil
	} else {
		return nil, err
	}
}

func GetRSAPublicKey(kid string) *rsa.PublicKey {
	resp, err := http.Get("https://appleid.apple.com/auth/keys")
	if err != nil {
		return nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil
	}
	var authKeys AppleJwtAuthKeys
	err = json.Unmarshal(body, &authKeys)
	if err != nil {
		return nil
	}
	//fmt.Println(authKeys)
	// 获取验证所需的公钥
	var pubKey rsa.PublicKey
	// 通过cliHeader的kid比对获取n和e值 构造公钥
	for _, val := range authKeys.Keys {
		if val.Kid == kid {
			nByte, _ := base64.RawURLEncoding.DecodeString(val.N)
			nData := new(big.Int).SetBytes(nByte)

			eByte, _ := base64.RawURLEncoding.DecodeString(val.E)
			eData := new(big.Int).SetBytes(eByte)

			pubKey.N = nData
			pubKey.E = int(eData.Uint64())
			break
		}
	}

	if pubKey.E <= 0 {
		return nil
	}
	return &pubKey
}
标签: appleid golang jwt
最后更新:2023年6月14日

大明

靠写代码养家的开发者。

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2023 疯狂编程网. ALL RIGHTS RESERVED.

京ICP备2022013580号-1