### Install Go Sign In With Apple Library (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Installs the Go library for Apple Sign In integration using the standard Go module system. This command fetches the latest version of the package and makes it available for import in your Go projects. ```bash go get github.com/Timothylock/go-signin-with-apple import "github.com/Timothylock/go-signin-with-apple/apple" ``` -------------------------------- ### Configure Custom HTTP Client with Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Enables advanced HTTP client configurations, such as custom timeouts and transport settings. This is useful for scenarios requiring specific network behavior or middleware integration. The example demonstrates creating a custom `http.Client` and passing it to `apple.NewWithOptions`. ```go package main import ( "context" "fmt" "net/http" "time" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { // Create custom HTTP client with extended timeout customClient := &http.Client{ Timeout: 10 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 10, IdleConnTimeout: 30 * time.Second, }, } // Create validation client with custom options client := apple.NewWithOptions(apple.ClientOptions{ ValidationURL: apple.ValidationURL, // Use default or custom URL RevokeURL: apple.RevokeURL, // Use default or custom URL Client: customClient, // Custom HTTP client }) clientID := "com.your.app" clientSecret := "your_generated_secret" vReq := apple.AppValidationTokenRequest{ ClientID: clientID, ClientSecret: clientSecret, Code: "c1234567890abcdef.0.abcd.1234567890", } var resp apple.ValidationResponse err := client.VerifyAppToken(context.Background(), vReq, &resp) if err != nil { fmt.Printf("error verifying: %s\n", err.Error()) return } fmt.Printf("Validation successful: %s\n", resp.AccessToken) } ``` -------------------------------- ### Get Real User Status from Apple Token Claims (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md This Go code snippet demonstrates how to import the necessary package, validate an Apple sign-in token, extract claims, and specifically retrieve the 'real_user_status' from the claims. It relies on the go-signin-with-apple library and assumes a prior token validation step has occurred. ```go import "github.com/Timothylock/go-signin-with-apple/apple" // ... Code to validate token ... claim, _ := apple.GetClaims(resp.IDToken) realUserStatus := (*claim)["real_user_status"] ``` -------------------------------- ### Extract User Claims from JWT ID Token with Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Parses a JWT ID token to extract user claims, including email, verification status, and fraud detection data. It provides utility functions `apple.GetUniqueID` to get the unique user identifier and `apple.GetClaims` to retrieve all claims as a map. Individual claims can then be accessed and type-asserted. ```go package main import ( "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { // ID token received from validation response idToken := "eyJraWQiOiJXNldjT0tCIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLnlvdXIuYXBwIiwiZXhwIjoxNjE2MTYxNjE2LCJpYXQiOjE2MTYwNzUyMTYsInN1YiI6IjAwMTIzNC5hYmMxMjNkZWY0NTYuNzg5MCIsImVtYWlsIjoidXNlckBwcml2YXRlcmVsYXkuYXBwbGVpZC5jb20iLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJpc19wcml2YXRlX2VtYWlsIjoidHJ1ZSIsInJlYWxfdXNlcl9zdGF0dXMiOjF9...." // Extract unique user ID userID, err := apple.GetUniqueID(idToken) if err != nil { fmt.Printf("failed to get unique ID: %s\n", err.Error()) return } // Extract all claims claims, err := apple.GetClaims(idToken) if err != nil { fmt.Printf("failed to get claims: %s\n", err.Error()) return } // Access individual claims email := (*claims)["email"].(string) emailVerified := (*claims)["email_verified"].(string) isPrivateEmail := (*claims)["is_private_email"].(string) // Real user status (iOS 14+): 0 = unsupported, 1 = unknown, 2 = likely real realUserStatus := (*claims)["real_user_status"] // Token metadata issuer := (*claims)["iss"].(string) audience := (*claims)["aud"].(string) issuedAt := (*claims)["iat"].(float64) expiresAt := (*claims)["exp"].(float64) fmt.Printf("User ID: %s\n", userID) fmt.Printf("Email: %s\n", email) fmt.Printf("Email Verified: %s\n", emailVerified) fmt.Printf("Is Private Email: %s\n", isPrivateEmail) fmt.Printf("Real User Status: %v\n", realUserStatus) fmt.Printf("Issuer: %s\n", issuer) fmt.Printf("Audience: %s\n", audience) fmt.Printf("Issued At: %.0f\n", issuedAt) fmt.Printf("Expires At: %.0f\n", expiresAt) // Output: // User ID: 001234.abc123def456.7890 // Email: user@privaterelay.appleid.com // Email Verified: true // Is Private Email: true // Real User Status: 1 // Issuer: https://appleid.apple.com // Audience: com.your.app // Issued At: 1616075216 // Expires At: 1616161616 } ``` -------------------------------- ### Get Claims from Apple ID Token (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Retrieves claims, including email information, from an Apple ID token. This function decodes the JWT and provides access to fields like 'email', 'email_verified', and 'is_private_email'. This is useful for obtaining user contact details after successful authentication. ```go import "github.com/Timothylock/go-signin-with-apple/apple" // Code to validate token ... reflect.TypeOf(response) // ValidationResponse reflect.TypeOf(response.IdToken) // String claim, _ := apple.GetClaims(resp.IDToken) email := (*claim)("email") emailVerified := (*claim)("email_verified") isPrivateEmail := (*claim)("is_private_email") ``` -------------------------------- ### Get Unique User ID from Apple ID Token (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Extracts the unique subject identifier for a user from an Apple ID token. This ID is present in the 'id_token' field of the validation response. The function decodes the JWT and retrieves the 'sub' claim, which uniquely identifies the user across different apps from the same developer. ```go import "github.com/Timothylock/go-signin-with-apple/apple" // Code to validate token ... reflect.TypeOf(response) // ValidationResponse reflect.TypeOf(response.IdToken) // String id := apple.GetUniqueID(response.IdToken) fmt.Println(id) ``` -------------------------------- ### New Validation Client for Apple Sign In (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Initializes a new client instance for performing Apple Sign In token validation. This client is used to interact with Apple's authentication services. The `New()` function creates a default client, which can then be used to call verification methods. ```go import "github.com/Timothylock/go-signin-with-apple/apple" // Generate a new validation client client := apple.New() ``` -------------------------------- ### Validate iOS App Token and Extract User Info with Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Verifies authorization codes received from iOS applications and extracts associated user information. This process involves generating a client secret, creating a validation client, and then calling the `VerifyAppToken` function. It returns the unique user ID, claims (like email and verification status), and tokens. Dependencies include the `context` package and the `github.com/Timothylock/go-signin-with-apple/apple` library. ```go package main import ( "context" "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { teamID := "XXXXXXXXXX" clientID := "com.your.app" keyID := "XXXXXXXXXX" secret := `-----BEGIN PRIVATE KEY----- YOUR_SECRET_PRIVATE_KEY -----END PRIVATE KEY-----` // Generate client secret clientSecret, err := apple.GenerateClientSecret(secret, teamID, clientID, keyID) if err != nil { fmt.Printf("error generating secret: %s\n", err.Error()) return } // Create validation client client := apple.New() // Prepare validation request vReq := apple.AppValidationTokenRequest{ ClientID: clientID, ClientSecret: clientSecret, Code: "c1234567890abcdef.0.abcd.1234567890", // Authorization code from iOS } var resp apple.ValidationResponse // Verify the token err = client.VerifyAppToken(context.Background(), vReq, &resp) if err != nil { fmt.Printf("error verifying: %s\n", err.Error()) return } // Check for Apple errors if resp.Error != "" { fmt.Printf("apple returned an error: %s - %s\n", resp.Error, resp.ErrorDescription) return } // Extract unique user ID uniqueID, err := apple.GetUniqueID(resp.IDToken) if err != nil { fmt.Printf("failed to get unique ID: %s\n", err.Error()) return } // Extract claims (email, verification status, etc.) claims, err := apple.GetClaims(resp.IDToken) if err != nil { fmt.Printf("failed to get claims: %s\n", err.Error()) return } email := (*claims)("email") emailVerified := (*claims)("email_verified") isPrivateEmail := (*claims)("is_private_email") realUserStatus := (*claims)("real_user_status") // iOS 14+ devices only fmt.Printf("User ID: %s\n", uniqueID) fmt.Printf("Email: %s\n", email) fmt.Printf("Email Verified: %v\n", emailVerified) fmt.Printf("Private Email: %v\n", isPrivateEmail) fmt.Printf("Real User Status: %v\n", realUserStatus) fmt.Printf("Access Token: %s\n", resp.AccessToken) fmt.Printf("Refresh Token: %s\n", resp.RefreshToken) fmt.Printf("Expires In: %d seconds\n", resp.ExpiresIn) // Output: // User ID: 001234.abc123def456.7890 // Email: user@privaterelay.appleid.com // Email Verified: true // Private Email: true // Real User Status: 1 // Access Token: a1b2c3d4e5... // Refresh Token: r1b2c3d4e5... // Expires In: 3600 } ``` -------------------------------- ### Verify App Token Request Structure (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Defines the structure for requesting verification of an Apple Sign In app token. This struct includes fields for the client ID, the generated client secret, and the authorization code obtained from the user's interaction with the Sign In with Apple button. ```go vReq := apple.AppValidationTokenRequest{ ClientID: clientID, ClientSecret: secret, Code: "the_authorization_code_to_validate", } ``` -------------------------------- ### Refresh Access Token using Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Obtains a new access token using a stored refresh token, eliminating the need for direct user interaction. This process requires the client ID, a generated client secret, and the refresh token. The function returns a refresh response containing the new access token, token type, and expiration time, or an error if the refresh fails. Dependencies include the 'go-signin-with-apple/apple' package. ```go package main import ( "context" "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { teamID := "XXXXXXXXXX" clientID := "com.your.app" keyID := "XXXXXXXXXX" secret := `-----BEGIN PRIVATE KEY----- YOUR_SECRET_PRIVATE_KEY -----END PRIVATE KEY----- ` clientSecret, err := apple.GenerateClientSecret(secret, teamID, clientID, keyID) if err != nil { fmt.Printf("error generating secret: %s\n", err.Error()) return } client := apple.New() vReq := apple.ValidationRefreshRequest{ ClientID: clientID, ClientSecret: clientSecret, RefreshToken: "r1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", // Stored refresh token } var resp apple.RefreshResponse err = client.VerifyRefreshToken(context.Background(), vReq, &resp) if err != nil { fmt.Printf("error verifying: %s\n", err.Error()) return } if resp.Error != "" { fmt.Printf("apple returned an error: %s - %s\n", resp.Error, resp.ErrorDescription) return } fmt.Printf("New Access Token: %s\n", resp.AccessToken) fmt.Printf("Token Type: %s\n", resp.TokenType) fmt.Printf("Expires In: %d seconds\n", resp.ExpiresIn) // Output: // New Access Token: a9b8c7d6e5... // Token Type: bearer // Expires In: 3600 } ``` -------------------------------- ### Verify App Token with Apple Sign In (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Verifies an authorization code received from the Apple Sign In app. It requires a client ID, a generated client secret, and the authorization code. The function returns a validation response containing token details if successful. Ensure the context is properly managed for the request. ```go import "github.com/Timothylock/go-signin-with-apple/apple" // Generate the client secret used to authenticate with Apple's validation servers // Refer to the example files to see where to get secret, teamID, clientID, keyID secret, _ := apple.GenerateClientSecret(secret, teamID, clientID, keyID) // Generate a new validation client client := apple.New() vReq := apple.AppValidationTokenRequest{ ClientID: clientID, ClientSecret: secret, Code: "the_authorization_code_to_validate", } var resp apple.ValidationResponse // Do the verification client.VerifyAppToken(context.Background(), vReq, &resp) unique, _ := apple.GetUniqueID(resp.IDToken) // Voila! fmt.Println(unique) ``` -------------------------------- ### Validate Web Token using Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Verifies authorization codes obtained from web-based Sign in with Apple flows. It requires the client ID, generated client secret, the authorization code, and the registered redirect URI. The function returns a validation response containing user information and tokens, or an error if validation fails. Dependencies include the 'go-signin-with-apple/apple' package. ```go package main import ( "context" "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { teamID := "XXXXXXXXXX" clientID := "com.your.services" // Services ID for web keyID := "XXXXXXXXXX" secret := `-----BEGIN PRIVATE KEY----- YOUR_SECRET_PRIVATE_KEY -----END PRIVATE KEY----- ` clientSecret, err := apple.GenerateClientSecret(secret, teamID, clientID, keyID) if err != nil { fmt.Printf("error generating secret: %s\n", err.Error()) return } client := apple.New() vReq := apple.WebValidationTokenRequest{ ClientID: clientID, ClientSecret: clientSecret, Code: "c1234567890abcdef.0.abcd.1234567890", RedirectURI: "https://example.com/auth/callback", // Must match registered URL } var resp apple.ValidationResponse err = client.VerifyWebToken(context.Background(), vReq, &resp) if err != nil { fmt.Printf("error verifying: %s\n", err.Error()) return } if resp.Error != "" { fmt.Printf("apple returned an error: %s - %s\n", resp.Error, resp.ErrorDescription) return } uniqueID, err := apple.GetUniqueID(resp.IDToken) if err != nil { fmt.Printf("failed to get unique ID: %s\n", err.Error()) return } claims, err := apple.GetClaims(resp.IDToken) if err != nil { fmt.Printf("failed to get claims: %s\n", err.Error()) return } fmt.Printf("User ID: %s\n", uniqueID) fmt.Printf("Email: %s\n", (*claims)["email"]) fmt.Printf("Refresh Token: %s\n", resp.RefreshToken) } ``` -------------------------------- ### Generate JWT Client Secret for Apple Authentication Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Generates a JSON Web Token (JWT) client secret required for authenticating with Apple's validation servers. This secret is used in various Sign in with Apple operations and has a lifespan of 180 days. It requires your Apple Developer portal credentials including Team ID, Services ID, Key ID, and your private key content. ```go package main import ( "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { // Your 10-character Team ID from Apple Developer portal teamID := "XXXXXXXXXX" // Your Services ID (e.g., com.example.services) clientID := "com.your.app" // 10-character Key ID from the portal keyID := "XXXXXXXXXX" // Private key content from the .p8 file downloaded from Apple secret := `-----BEGIN PRIVATE KEY----- MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg... -----END PRIVATE KEY-----` // Generate the client secret clientSecret, err := apple.GenerateClientSecret(secret, teamID, clientID, keyID) if err != nil { fmt.Printf("error generating secret: %s\n", err.Error()) return } fmt.Printf("Client Secret: %s\n", clientSecret) // Output: Client Secret: eyJhbGciOiJFUzI1NiIsImtpZCI6IlhYWFhYWFhYWFgifQ... } ``` -------------------------------- ### Generate Client Secret for Apple Sign In (Go) Source: https://github.com/timothylock/go-signin-with-apple/blob/master/README.md Generates a JWT client secret required for authenticating requests to Apple's validation servers. This function takes your private key, team ID, client ID, and key ID as input. Ensure you have the necessary permissions to create and access these credentials in your Apple Developer account. ```go import "github.com/Timothylock/go-signin-with-apple/apple" // Your 10-character Team ID team_id := "XXXXXXXXXX" // Your Services ID, e.g. com.aaronparecki.services client_id := "come.change.me" // Find the 10-char Key ID value from the portal key_id := "XXXXXXXXXX" secret := `Your key that starts with -----BEGIN PRIVATE KEY-----` secret, _ := apples.GenerateClientSecret(secret, team_id, client_id, key_id) fmt.Println(secret) ``` -------------------------------- ### Revoke Access Token using Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Invalidates a specific access token, effectively ending the associated user session immediately. This operation requires the client ID, a generated client secret, and the access token to be revoked. The function returns a revoke response indicating success or failure, or an error if the revocation process itself encounters an issue. Dependencies include the 'go-signin-with-apple/apple' package. ```go package main import ( "context" "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { teamID := "XXXXXXXXXX" clientID := "com.your.app" keyID := "XXXXXXXXXX" secret := `-----BEGIN PRIVATE KEY----- YOUR_SECRET_PRIVATE_KEY -----END PRIVATE KEY----- ` clientSecret, err := apple.GenerateClientSecret(secret, teamID, clientID, keyID) if err != nil { fmt.Printf("error generating secret: %s\n", err.Error()) return } client := apple.New() vReq := apple.RevokeAccessTokenRequest{ ClientID: clientID, ClientSecret: clientSecret, AccessToken: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", // Token to revoke } var resp apple.RevokeResponse err = client.RevokeAccessToken(context.Background(), vReq, &resp) if err != nil { fmt.Printf("error revoking: %s\n", err.Error()) return } if resp.Error != "" { fmt.Printf("apple returned an error: %s - %s\n", resp.Error, resp.ErrorDescription) return } fmt.Println("Access token successfully revoked") // Output: Access token successfully revoked } ``` -------------------------------- ### Revoke Refresh Token with Go Source: https://context7.com/timothylock/go-signin-with-apple/llms.txt Permanently invalidates a refresh token, preventing it from being used to generate new tokens. This function requires client credentials and the specific refresh token to be revoked. It utilizes the `apple.RevokeRefreshTokenRequest` struct and the `client.RevokeRefreshToken` method from the go-signin-with-apple library. ```go package main import ( "context" "fmt" "github.com/Timothylock/go-signin-with-apple/apple" ) func main() { teamID := "XXXXXXXXXX" clientID := "com.your.app" keyID := "XXXXXXXXXX" secret := `-----BEGIN PRIVATE KEY----- YOUR_SECRET_PRIVATE_KEY -----END PRIVATE KEY----- ` clientSecret, err := apple.GenerateClientSecret(secret, teamID, clientID, keyID) if err != nil { fmt.Printf("error generating secret: %s\n", err.Error()) return } client := apple.New() vReq := apple.RevokeRefreshTokenRequest{ ClientID: clientID, ClientSecret: clientSecret, RefreshToken: "r1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", // Token to revoke } var resp apple.RevokeResponse err = client.RevokeRefreshToken(context.Background(), vReq, &resp) if err != nil { fmt.Printf("error revoking: %s\n", err.Error()) return } if resp.Error != "" { fmt.Printf("apple returned an error: %s - %s\n", resp.Error, resp.ErrorDescription) return } fmt.Println("Refresh token successfully revoked") // Output: Refresh token successfully revoked } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.