mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
* Add DenyLists parsing * Remove unneeded returned error * Plug global denylist into Command * app creation: apply denylist to backchannel logout URI * Inject denylist to backchannel logout worker * webhook config: validate against blocked URLs * Add notificationsWebhook denylist target * command: Add SMTP endpoint validation against blocklist * command: Add SMS endpoint validation against blocklist * Validate webhook endpoint against denylist on channel notification * Remove unused tests * handle deprecated denylists * remove unintended denylist entry in deprecated list * use single http client * fix tests * update comments * fixes * cleanup * address comments * fix merge --------- Co-authored-by: Livio Spring <[email protected]>
72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
package apple
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-jose/go-jose/v4"
|
|
"github.com/zitadel/oidc/v3/pkg/crypto"
|
|
openid "github.com/zitadel/oidc/v3/pkg/oidc"
|
|
|
|
zcrypto "github.com/zitadel/zitadel/internal/crypto"
|
|
"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, httpClient *http.Client, 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, httpClient, 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) {
|
|
pk, err := BytesToPrivateKey(key)
|
|
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().Add(-2 * time.Second)
|
|
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)
|
|
}
|
|
|
|
func BytesToPrivateKey(key []byte) (*ecdsa.PrivateKey, error) {
|
|
return zcrypto.BytesToPrivateKeyPKCS8[*ecdsa.PrivateKey](key)
|
|
}
|