美文网首页
golang 苹果一键登录 sing in with apple

golang 苹果一键登录 sing in with apple

作者: zfh_51d2 | 来源:发表于2020-08-16 19:15 被阅读0次

    前言

    本文是对AppleID登录接入的相关总结,希望对其他人能有帮助。

    sing in with apple

    官方文档

    “通过 Apple 登录”让用户能用自己的 Apple ID 轻松登录您的 app 和网站。用户不必填写表单、验证电子邮件地址和选择新密码,就可以使用“通过 Apple 登录”设置帐户并立即开始使用您的 app。所有帐户都通过双重认证受到保护,具有极高的安全性,Apple 亦不会跟踪用户在您的 app 或网站中的活动。

    代码

    package main
    
    import (
        "crypto/ecdsa"
        "crypto/x509"
        "encoding/json"
        "encoding/pem"
        "errors"
        "github.com/dgrijalva/jwt-go"
        "io/ioutil"
        "net/http"
        "net/url"
        "strings"
        "time"
    )
    
    var (
        secret = `-----BEGIN PRIVATE KEY-----
        your PRIVATE KEY-
    -----END PRIVATE KEY-----`
        keyId        = "keyId"
        teamId       = "teamId"
        clientID     = "clientID" //网页授权登录填写的是Services Id,App端登录需要的是AppId
        appID        = "appID"
        redirectUrl  = ""
        authTokenUrl = "https://appleid.apple.com/auth/token"
    )
    
    // create client_secret
    func GetAppleSecret() string {
        token := &jwt.Token{
            Header: map[string]interface{}{
                "alg": "ES256",
                "kid": keyId,
            },
            Claims: jwt.MapClaims{
                "iss": teamId,
                "iat": time.Now().Unix(),
                // constraint: exp - iat <= 180 days
                "exp": time.Now().Add(24 * time.Hour).Unix(),
                "aud": "https://appleid.apple.com",
                "sub": appID,
            },
            Method: jwt.SigningMethodES256,
        }
    
        ecdsaKey, _ := AuthKeyFromBytes([]byte(secret))
        ss, _ := token.SignedString(ecdsaKey)
        return ss
    }
    
    func AuthKeyFromBytes(key []byte) (*ecdsa.PrivateKey, error) {
        var err error
    
        var block *pem.Block
        if block, _ = pem.Decode(key); block == nil {
            return nil, errors.New("token: AuthKey must be a valid .p8 PEM file")
        }
    
        var parsedKey interface{}
        if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
            return nil, err
        }
    
        var pkey *ecdsa.PrivateKey
        var ok bool
        if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
            return nil, errors.New("token: AuthKey must be of type ecdsa.PrivateKey")
        }
    
        return pkey, nil
    }
    
    type AppleAuthTokenRes struct {
        Error        string `json:"error"`
        AccessToken  string `json:"access_token"`
        ExpiresIn    int    `json:"expires_in"`
        IDToken      string `json:"id_token"`
        RefreshToken string `json:"refresh_token"`
        TokenType    string `json:"token_type"`
    }
    
    func AppleAuthToken(code string) (*AppleAuthTokenRes, error) {
        form := url.Values{}
        form.Set("client_id", appID)
        form.Set("client_secret", GetAppleSecret())
        form.Set("code", code)
        form.Set("grant_type", "authorization_code")
        form.Set("redirect_uri", redirectUrl)
    
        var request *http.Request
        var err error
        if request, err = http.NewRequest("POST", authTokenUrl, strings.NewReader(form.Encode())); err != nil {
            return nil, err
        }
        request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    
        var response *http.Response
        if response, err = http.DefaultClient.Do(request); nil != err {
            return nil, err
        }
        defer response.Body.Close()
    
        data, err := ioutil.ReadAll(response.Body)
        if err != nil {
            return nil, err
        }
    
        res := &AppleAuthTokenRes{}
        err = json.Unmarshal(data, res)
        if err != nil {
            return nil, err
        }
    
        if res.Error != "" {
            return res, errors.New(res.Error)
        }
        return res, nil
    }
    

    遇到的问题

    报错invalid_grant

    可能原因1:
    前端传过来的code使用一次或者过几分钟就失效了,需要重新生成。
    可能原因2:
    网页授权登录填写的是Services Id,App端登录需要的是AppI。

    相关文章

      网友评论

          本文标题:golang 苹果一键登录 sing in with apple

          本文链接:https://www.haomeiwen.com/subject/tkhxjktx.html