go_signin_with_apple

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2020 License: MIT Imports: 12 Imported by: 0

README

Go Sign In With Apple

codecov Build Status Codacy Badge

A library for validating Apple Sign In tokens.

Usage

There are several example files based on your particular use case which can be found below:

Example

While it is recommended to look at the specific example file, here is validating an app token:

import "github.com/huydang284/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_token_to_validate",
}

var resp apple.ValidationResponse

// Do the verification
client.VerifyAppToken(context.Background(), vReq, &resp)

unique, _ := apple.GetUniqueID(resp.IDToken)

// Voila!
fmt.Println(unique)
Generating Client Secret

Apple requires a JWT token along with your validation request to authenticate your request. A token can be generated by calling the GenerateClientSecret function included. Check secret.go to see exactly how to obtain the parameters required by the function. Note that your account might not have permissions to view/create service IDs and keys required by this function.

import "github.com/huydang284/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 in -----BEGIN PRIVATE KEY-----`

secret, _ := apples.GenerateClientSecret(secret, team_id, client_id, key_id)
fmt.Println(secret)
Validating Token

To validate a token, you must create a new validation Client then call the respective Verify function.

import "github.com/huydang284/go-signin-with-apple/apple"

...

// Generate a new validation client
client := apple.New()

vReq := apple.AppValidationTokenRequest{
	ClientID:     clientID,
	ClientSecret: secret,
	Code:         "the_token_to_validate",
}

var resp apple.ValidationResponse

// Do the verification
client.VerifyAppToken(context.Background(), vReq, &resp)

Obtaining Unique Subject ID

A subject ID is included in the id_token field of the response which when decoded, has a subject that can uniquely identify the user. A helper function is included to obtain this subject ID: GetUniqueID

import "github.com/huydang284/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)
Obtaining Email

Apple recently added support for the including information about the user in their response. As of right now, you have access to the following:

  • email
  • email_verified - whether or not the user has validated their email with Apple
  • private_email - whether or not the email is a private relay email from Apple
import "github.com/huydang284/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"]

Contributing

Make sure tests pass, submit a PR, and let's get going!

License

go-signin-with-apple is licensed under the MIT.

Documentation

Index

Constants

View Source
const (
	// ValidationURL is the endpoint for verifying tokens
	ValidationURL string = "https://appleid.apple.com/auth/token"
	// ContentType is the one expected by Apple
	ContentType string = "application/x-www-form-urlencoded"
	// UserAgent is required by Apple or the request will fail
	UserAgent string = "go-signin-with-apple"
	// AcceptHeader is the content that we are willing to accept
	AcceptHeader string = "application/json"
)

Variables

This section is empty.

Functions

func GenerateClientSecret

func GenerateClientSecret(signingKey, teamID, clientID, keyID string) (string, error)

GenerateClientSecret generates the client secret used to make requests to the validation server. The secret expires after 6 months

signingKey - Private key from Apple obtained by going to the keys section of the developer section teamID - Your 10-character Team ID clientID - Your Services ID, e.g. com.aaronparecki.services keyID - Find the 10-char Key ID value from the portal

func GetClaims

func GetClaims(idToken string) (*jwt.Claims, error)

GetClaims decodes the id_token response and returns the JWT claims to identify the user

func GetUniqueID

func GetUniqueID(idToken string) (string, error)

GetUniqueID decodes the id_token response and returns the unique subject ID to identify the user

Types

type AppValidationTokenRequest

type AppValidationTokenRequest struct {
	// ClientID is the package name of your app
	ClientID string

	// ClientSecret is secret generated as a JSON Web Token that uses the secret key generated by the WWDR portal.
	// It can also be generated using the GenerateClientSecret function provided in this package
	ClientSecret string

	// Code is the authorization code received from your application’s user agent.
	// The code is single use only and valid for five minutes.
	Code string
}

AppValidationTokenRequest is based off of https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client implements ValidationClient

func New

func New() *Client

New creates a Client object

func NewWithURL

func NewWithURL(url string) *Client

NewWithURL creates a Client object with a custom URL provided

func (*Client) VerifyAppToken

func (c *Client) VerifyAppToken(ctx context.Context, reqBody AppValidationTokenRequest, result interface{}) error

VerifyAppToken sends the AppValidationTokenRequest and gets validation result

func (*Client) VerifyRefreshToken

func (c *Client) VerifyRefreshToken(ctx context.Context, reqBody ValidationRefreshRequest, result interface{}) error

VerifyRefreshToken sends the WebValidationTokenRequest and gets validation result

func (*Client) VerifyWebToken

func (c *Client) VerifyWebToken(ctx context.Context, reqBody WebValidationTokenRequest, result interface{}) error

VerifyWebToken sends the WebValidationTokenRequest and gets validation result

type RefreshResponse

type RefreshResponse struct {
	// (Reserved for future use) A token used to access allowed data. Currently, no data set has been defined for access.
	AccessToken string `json:"access_token"`

	// The type of access token. It will always be "bearer".
	TokenType string `json:"token_type"`

	// The amount of time, in seconds, before the access token expires. You can revalidate with this token
	ExpiresIn int `json:"expires_in"`

	// Used to capture any error returned by the endpoint. Do not trust the response if this error is not nil
	Error string `json:"error"`
}

RefreshResponse is a subset of ValidationResponse returned by Apple

type ValidationClient

type ValidationClient interface {
	VerifyWebToken(ctx context.Context, reqBody WebValidationTokenRequest, result interface{}) error
	VerifyAppToken(ctx context.Context, reqBody AppValidationTokenRequest, result interface{}) error
	VerifyRefreshToken(ctx context.Context, reqBody ValidationRefreshRequest, result interface{}) error
}

ValidationClient is an interface to call the validation API

type ValidationRefreshRequest

type ValidationRefreshRequest struct {
	// ClientID is the "Services ID" value that you get when navigating to your "sign in with Apple"-enabled service ID
	ClientID string

	// ClientSecret is secret generated as a JSON Web Token that uses the secret key generated by the WWDR portal.
	// It can also be generated using the GenerateClientSecret function provided in this package
	ClientSecret string

	// RefreshToken is the refresh token given during a previous validation
	RefreshToken string
}

ValidationRefreshRequest is based off of https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens

type ValidationResponse

type ValidationResponse struct {
	// (Reserved for future use) A token used to access allowed data. Currently, no data set has been defined for access.
	AccessToken string `json:"access_token"`

	// The type of access token. It will always be "bearer".
	TokenType string `json:"token_type"`

	// The amount of time, in seconds, before the access token expires. You can revalidate with the "RefreshToken"
	ExpiresIn int `json:"expires_in"`

	// The refresh token used to regenerate new access tokens. Store this token securely on your server.
	RefreshToken string `json:"refresh_token"`

	// A JSON Web Token that contains the user’s identity information.
	IDToken string `json:"id_token"`

	// Used to capture any error returned by the endpoint. Do not trust the response if this error is not nil
	Error string `json:"error"`
}

ValidationResponse is based off of https://developer.apple.com/documentation/signinwithapplerestapi/tokenresponse

type WebValidationTokenRequest

type WebValidationTokenRequest struct {
	// ClientID is the "Services ID" value that you get when navigating to your "sign in with Apple"-enabled service ID
	ClientID string

	// ClientSecret is secret generated as a JSON Web Token that uses the secret key generated by the WWDR portal.
	// It can also be generated using the GenerateClientSecret function provided in this package
	ClientSecret string

	// Code is the authorization code received from your application’s user agent.
	// The code is single use only and valid for five minutes.
	Code string

	// RedirectURI is the destination URI the code was originally sent to.
	// Redirect URLs must be registered with Apple. You can register up to 10. Apple will throw an error with IP address
	// URLs on the authorization screen, and will not let you add localhost in the developer portal.
	RedirectURI string
}

WebValidationTokenRequest is based off of https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL