-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapi_generating_tokens_for_api_requests.go
More file actions
90 lines (81 loc) · 2.37 KB
/
api_generating_tokens_for_api_requests.go
File metadata and controls
90 lines (81 loc) · 2.37 KB
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package appstoreserverapi
import (
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"errors"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jws"
"github.com/lestrrat-go/jwx/v2/jwt"
"io"
"strings"
"time"
)
// 为 API 请求生成令牌
// Generating Tokens for API Requests
// doc: https://developer.apple.com/documentation/appstoreserverapi/generating_tokens_for_api_requests
// SignJwt Sign the JWT
// 创建签名: https://jwt.io/
// iss:
// 发行人: 您在 App Store Connect 中的密钥页面中的发行者 ID(例如:" 57246542-96fe-1a63-e053-0824d011072a")
// Issuer: Your issuer ID from the Keys page in App Store Connect (Ex: "57246542-96fe-1a63-e053-0824d011072a")
// kid:
// 秘钥:您在 App Store Connect 中的私钥 ID(例如2X9R4HXF34:)
// Key ID: Your private key ID from App Store Connect (Ex: 2X9R4HXF34)
// bid:
// 应用的BundleID(例如:“com.example.testbundleid2021”)
// Bundle ID: Your app’s bundle ID (Ex: “com.example.testbundleid2021”)
// pk:
// 签名的秘钥
// sign key
func SignJwt(cfg *Config) (string, error) {
iat := time.Now()
cfg.exp = iat.Add(cfg.ExpiryIn)
jwt.Settings(jwt.WithFlattenAudience(true))
j := jwt.New()
j.Set(jwt.IssuerKey, cfg.Iss)
j.Set(jwt.IssuedAtKey, iat)
j.Set(jwt.ExpirationKey, cfg.exp)
j.Set(jwt.AudienceKey, cfg.Aud)
j.Set("bid", cfg.Bid)
headers := jws.NewHeaders()
headers.Set("kid", cfg.Kid)
reader := strings.NewReader(cfg.Pk)
prikey, err := privateKeyFromReader(reader)
if err != nil {
return "", err
}
signed, err := jwt.Sign(j, jwt.WithKey(jwa.ES256, prikey, jws.WithProtectedHeaders(headers)))
return string(signed), err
}
var (
ErrPrivateKeyNotValidPEM = errors.New("pk is not a valid PEM type")
ErrPrivateKeyNotValidPKCS8 = errors.New("pk must be a encoded PKCS#8 type")
ErrPrivateKeyNotECDSA = errors.New("pk must be of ECDSA type")
)
func privateKeyFromReader(rd *strings.Reader) (*ecdsa.PrivateKey, error) {
b := make([]byte, rd.Len())
for {
_, err := rd.Read(b)
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
}
by, _ := pem.Decode(b)
if by == nil {
return nil, ErrPrivateKeyNotValidPEM
}
key, err := x509.ParsePKCS8PrivateKey(by.Bytes)
if err != nil {
return nil, ErrPrivateKeyNotValidPKCS8
}
switch pk := key.(type) {
case *ecdsa.PrivateKey:
return pk, nil
default:
return nil, ErrPrivateKeyNotECDSA
}
}