/
secret.go
73 lines (56 loc) · 1.74 KB
/
secret.go
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
// secret generates the secret used for validation requests.
package auth
import (
"crypto/x509"
"encoding/pem"
"errors"
"net/http"
"time"
"github.com/golang-jwt/jwt/v4"
)
const (
AUDIENCE = "https://appleid.apple.com"
)
type httpClient interface {
Do(req *http.Request) (resp *http.Response, err error)
}
type Request struct {
// 10-char App Id prefix found in App identifiers section
TeamID string
//ClientID is the "Services ID" value that you get when navigating to your "sign in with Apple"-enabled service ID
ClientID string
// This is the ID of the private key
KeyID string
// This is the private key file (.p8). You can download it from apple portal
ClientSecret []byte
HttpClient httpClient
}
// GenerateClientSecret returns a secret used to validate server requests
// SecretRequest is required to generate secret. Method will throw error
// if data is empty or wrong.
func (req *Request) GenerateClientSecret() (string, error) {
block, _ := pem.Decode(req.ClientSecret)
if block == nil {
return "", errors.New("pem block is empty after decoding")
}
prvKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return "", err
}
token := jwt.NewWithClaims(jwt.SigningMethodES256, req.NewRegisteredClaims())
token.Header["alg"] = "ES256"
token.Header["kid"] = req.KeyID
return token.SignedString(prvKey)
}
// NewRegisteredClaims generates jwt claims from SecretRequest.
func (req *Request) NewRegisteredClaims() *jwt.RegisteredClaims {
// Current time
now := time.Now()
return &jwt.RegisteredClaims{
Issuer: req.TeamID,
IssuedAt: &jwt.NumericDate{Time: now},
ExpiresAt: &jwt.NumericDate{Time: now.Add(time.Hour * 24 * 30)}, // 30 days
Audience: jwt.ClaimStrings{AUDIENCE},
Subject: req.ClientID,
}
}