mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-14 03:54:21 +00:00
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
|
package apple
|
||
|
|
||
|
import (
|
||
|
"crypto/x509"
|
||
|
"encoding/pem"
|
||
|
"time"
|
||
|
|
||
|
"github.com/zitadel/oidc/v2/pkg/crypto"
|
||
|
openid "github.com/zitadel/oidc/v2/pkg/oidc"
|
||
|
"gopkg.in/square/go-jose.v2"
|
||
|
|
||
|
"github.com/zitadel/zitadel/internal/idp"
|
||
|
"github.com/zitadel/zitadel/internal/idp/providers/oidc"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
name = "Apple"
|
||
|
issuer = "https://appleid.apple.com"
|
||
|
)
|
||
|
|
||
|
var _ idp.Provider = (*Provider)(nil)
|
||
|
|
||
|
// Provider is the [idp.Provider] implementation for Apple
|
||
|
type Provider struct {
|
||
|
*oidc.Provider
|
||
|
}
|
||
|
|
||
|
func New(clientID, teamID, keyID, callbackURL string, key []byte, scopes []string, options ...oidc.ProviderOpts) (*Provider, error) {
|
||
|
secret, err := clientSecretFromPrivateKey(key, teamID, clientID, keyID)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
options = append(options, oidc.WithResponseMode("form_post"))
|
||
|
rp, err := oidc.New(name, issuer, clientID, secret, callbackURL, scopes, oidc.DefaultMapper, options...)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &Provider{
|
||
|
Provider: rp,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// clientSecretFromPrivateKey uses the private key to create and sign a JWT, which has to be used as client_secret at Apple.
|
||
|
func clientSecretFromPrivateKey(key []byte, teamID, clientID, keyID string) (string, error) {
|
||
|
block, _ := pem.Decode(key)
|
||
|
b := block.Bytes
|
||
|
pk, err := x509.ParsePKCS8PrivateKey(b)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
signingKey := jose.SigningKey{
|
||
|
Algorithm: jose.ES256,
|
||
|
Key: &jose.JSONWebKey{Key: pk, KeyID: keyID},
|
||
|
}
|
||
|
signer, err := jose.NewSigner(signingKey, &jose.SignerOptions{})
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
iat := time.Now()
|
||
|
exp := iat.Add(time.Hour)
|
||
|
return crypto.Sign(&openid.JWTTokenRequest{
|
||
|
Issuer: teamID,
|
||
|
Subject: clientID,
|
||
|
Audience: []string{issuer},
|
||
|
ExpiresAt: openid.FromTime(exp),
|
||
|
IssuedAt: openid.FromTime(iat),
|
||
|
}, signer)
|
||
|
}
|