diff --git a/auth/social_login.go b/auth/social_login.go index 6d3c911d3dc61997c2782fb89da86fbfa21905a4..6ef1c276de5539d2af44d3617799015cfad51ef0 100644 --- a/auth/social_login.go +++ b/auth/social_login.go @@ -2,7 +2,10 @@ package auth import ( "context" + "github.com/Timothylock/go-signin-with-apple/apple" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/encryption" "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/errors" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/string_utils" "google.golang.org/api/idtoken" ) @@ -19,3 +22,52 @@ func ValidateGoogleIDToken(tokenString, clientID string) (string, error) { return email, nil } + +func ValidateAppleCode(code, redirectURI, encryptionKeySecret string, isDebug bool) (string, error) { + teamID := "7978M5K9YV" + clientID := "za.co.bob.auth.client" + keyID := "6X88ZTK5S4" + + signingKey, err := encryption.GetAppleSigningKey(encryptionKeySecret, isDebug) + if err != nil { + return "", errors.Error("apple signing key not set up") + } + + clientSecret, err := apple.GenerateClientSecret(signingKey, teamID, clientID, keyID) + if err != nil { + return "", err + } + + client := apple.New() + + var validationResponse apple.ValidationResponse + + err = client.VerifyWebToken(context.Background(), apple.WebValidationTokenRequest{ + ClientID: clientID, + ClientSecret: clientSecret, + RedirectURI: redirectURI, + Code: code, + }, &validationResponse) + + if err != nil { + return "", err + } + + if validationResponse.ErrorDescription != "" { + panic(validationResponse.ErrorDescription) + } + + claim, _ := apple.GetClaims(validationResponse.IDToken) + if claim == nil { + return "", errors.Error("invalid apple token") + } + + email := (*claim)["email"] + emailVerified := (*claim)["email_verified"] + + if emailVerified != "true" { + return "", errors.Error("email not verified") + } + + return string_utils.InterfaceToString(email) +} diff --git a/encryption/encryption_keys.go b/encryption/encryption_keys.go index 792d0e9d0d44275dcc7aaa26e3b5dd2766dc8549..6b0f9ec59a62faceebde957f1fd7cbce43d0b840 100644 --- a/encryption/encryption_keys.go +++ b/encryption/encryption_keys.go @@ -18,6 +18,7 @@ type EncryptionKeys struct { GenericEncryptionKey string `json:"generic_encryption_key"` BobGoEncryptionKey string `json:"bobgo_encryption_key"` ShipLogicPINEncryptionKey string `json:"ship_logic_pin_encryption_key"` + AppleSigningKey string `json:"apple_signing_key"` } func GetEncryptionKeys(secretID string, isDebug bool) (EncryptionKeys, error) { @@ -66,3 +67,8 @@ func GetShipLogicPINEncryptionKey(secretID string, isDebug bool) (string, error) encryptionKeys, err := GetEncryptionKeys(secretID, isDebug) return encryptionKeys.ShipLogicPINEncryptionKey, err } + +func GetAppleSigningKey(secretID string, isDebug bool) (string, error) { + encryptionKeys, err := GetEncryptionKeys(secretID, isDebug) + return encryptionKeys.AppleSigningKey, err +} diff --git a/go.mod b/go.mod index 7f1ab05be97e84ad05dcd14d9b3c1a6ee7979250..e48ccbba6f78a1c30950042dc8717046f1d6aad7 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( cloud.google.com/go/auth v0.13.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect + github.com/Timothylock/go-signin-with-apple v0.2.4 // indirect github.com/aws/aws-sdk-go v1.44.180 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect @@ -70,6 +71,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-pg/zerochecker v0.2.0 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect diff --git a/go.sum b/go.sum index 9b64ad7fbf232d6e757607d17c7400d3fea91dfd..014f865bde6fa2adb9fa2c7964d9787d35dfe629 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,8 @@ github.com/AfterShip/email-verifier v1.4.0/go.mod h1:JNPV1KZpTq4TArmss1NAOJsTD8J github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/MindscapeHQ/raygun4go v1.1.1 h1:fk3Uknv9kQxUIwL3mywwHQRyfq3PaR9lE/e40K+OcY0= github.com/MindscapeHQ/raygun4go v1.1.1/go.mod h1:NW0eWi2Qs00ZcctO6owrVMY+h2HxzJVgQGDrTj2ysw4= +github.com/Timothylock/go-signin-with-apple v0.2.4 h1:cOL5suxOU86bZ6oNpZFFHT0WL8EdABqm8dm04wVN+jw= +github.com/Timothylock/go-signin-with-apple v0.2.4/go.mod h1:uWYGAdyZQ+E2LMWRVI+prmYXApGJ+UaNVlwMwfT12S4= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= github.com/aws/aws-lambda-go v1.26.0 h1:6ujqBpYF7tdZcBvPIccs98SpeGfrt/UOVEiexfNIdHA= @@ -126,6 +128,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/string_utils/string_utils.go b/string_utils/string_utils.go index d00df87d5132f74dd24aa99afdec1e35ffe6a532..51ff85998feda726b95acbe7d989a2370d4b908d 100644 --- a/string_utils/string_utils.go +++ b/string_utils/string_utils.go @@ -211,6 +211,14 @@ func ToJSONString(object interface{}) (string, error) { return string(jsonBytes), nil } +func InterfaceToString(value interface{}) (string, error) { + str, ok := value.(string) + if !ok { + return "", fmt.Errorf("value is not a string") + } + return str, nil +} + func Int64ToString(number int64) string { return strconv.FormatInt(number, 10) }