Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions internal/api/provider/apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package provider

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"strconv"
"strings"
Expand All @@ -13,7 +15,34 @@ import (
"golang.org/x/oauth2"
)

const IssuerApple = "https://appleid.apple.com"
const DefaultAppleIssuer = "https://account.apple.com"
const OtherAppleIssuer = "https://appleid.apple.com"

func IsAppleIssuer(issuer string) bool {
return issuer == DefaultAppleIssuer || issuer == OtherAppleIssuer
}

func DetectAppleIDTokenIssuer(ctx context.Context, idToken string) (string, error) {
var payload struct {
Issuer string `json:"iss"`
}

parts := strings.Split(idToken, ".")
if len(parts) != 3 {
return "", fmt.Errorf("apple: invalid ID token")
}

payloadBytes, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return "", fmt.Errorf("apple: invalid ID token %w", err)
}

if err := json.Unmarshal(payloadBytes, &payload); err != nil {
return "", fmt.Errorf("apple: invalid ID token %w", err)
}

return payload.Issuer, nil
}

// AppleProvider stores the custom config for apple provider
type AppleProvider struct {
Expand Down Expand Up @@ -68,7 +97,7 @@ func NewAppleProvider(ctx context.Context, ext conf.OAuthProviderConfiguration)
logrus.Warn("Apple OAuth provider has URL config set which is ignored (check GOTRUE_EXTERNAL_APPLE_URL)")
}

oidcProvider, err := oidc.NewProvider(ctx, IssuerApple)
oidcProvider, err := oidc.NewProvider(ctx, DefaultAppleIssuer)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/api/provider/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ func ParseIDToken(ctx context.Context, provider *oidc.Provider, config *oidc.Con
switch token.Issuer {
case IssuerGoogle:
token, data, err = parseGoogleIDToken(token)
case IssuerApple:
token, data, err = parseAppleIDToken(token)
case IssuerLinkedin:
token, data, err = parseLinkedinIDToken(token)
case IssuerKakao:
Expand All @@ -66,6 +64,8 @@ func ParseIDToken(ctx context.Context, provider *oidc.Provider, config *oidc.Con
default:
if IsAzureIssuer(token.Issuer) {
token, data, err = parseAzureIDToken(token)
} else if IsAppleIssuer(token.Issuer) {
token, data, err = parseAppleIDToken(token)
} else {
token, data, err = parseGenericIDToken(token)
}
Expand Down
16 changes: 14 additions & 2 deletions internal/api/token_oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,22 @@ func (p *IdTokenGrantParams) getProvider(ctx context.Context, config *conf.Globa
var acceptableClientIDs []string

switch true {
case p.Provider == "apple" || p.Issuer == provider.IssuerApple:
case p.Provider == "apple" || provider.IsAppleIssuer(p.Issuer):
cfg = &config.External.Apple
providerType = "apple"
issuer = provider.IssuerApple
issuer = p.Issuer
if issuer == "" {
detectedIssuer, err := provider.DetectAppleIDTokenIssuer(ctx, p.IdToken)
if err != nil {
return nil, false, "", nil, apierrors.NewBadRequestError(apierrors.ErrorCodeValidationFailed, "Unable to detect issuer in ID token for Apple provider").WithInternalError(err)
}

if provider.IsAppleIssuer(detectedIssuer) {
issuer = detectedIssuer
} else {
return nil, false, "", nil, apierrors.NewBadRequestError(apierrors.ErrorCodeValidationFailed, "Detected ID token issuer is not an Apple ID token issuer")
}
}
acceptableClientIDs = append(acceptableClientIDs, config.External.Apple.ClientID...)

if config.External.IosBundleId != "" {
Expand Down
Loading