Skip to main content

Exchange an Authorization Code for an Access Token with PKCE

Explanation

The following code sample exchanges an Authorization Code for an Access Token. This Access Token can then be used to authorize requests to IMS services and APIs. You should retrieve the Authorization Code following the Generating an Authorization Code with PKCE sample.

package main

import (
"context"
"log"

cv "github.com/nirasan/go-oauth-pkce-code-verifier"
"golang.org/x/oauth2"
)

const (
ClientID = "client-id"
RedirectUrl = "http://localhost:8080/redirect"

// The Authorization Code should have already been retrieved from the IMS
// Platform Auth service. See the "Generating an Authorization Code with
// PKCE" code sample on how to get an AuthorizationCode.
AuthorizationCode = "authorization-code"
)

func generatePKCECodeChallenge() (string, string, error) {
codeVerifier, err := cv.CreateCodeVerifier()
if err != nil {
return "", "", err
}
return codeVerifier.CodeChallengeS256(), codeVerifier.String(), nil
}

func main() {
// First we set up our OAuth2 configuration.
//
// We include the ClientID from our OAuth Client, we
// specify the Authorize and Token URLs, and we set up the redirect URL.
// The values for these fields are set up when you create the OAuth Client
// or are provided in the documentation. The Client Secret is left empty,
// as we are using a public client.
//
// Finally, we specify the Scopes we want to return. The Scopes specified
// here mean we return all permissions available to the user. For more
// information on what this means please view the IMS Permissions and Scopes
// guide.
config := oauth2.Config{
ClientID: ClientID,
Endpoint: oauth2.Endpoint{
AuthURL: "https://platform-auth.improbable.io/auth/v1/authorize",
TokenURL: "https://platform-auth.improbable.io/auth/v1/token",
},
RedirectURL: RedirectUrl,
Scopes: []string{"[*]:*"},
}

// The challenge is used in the Authorization Code request, so isn't
// referenced further in this code sample. The verifier, however, is used in
// the exchange and allows the auth service to verify that the authorize
// request and the exchange were made by the same entity.
//challenge, verifier, err := generatePKCECodeChallenge()
_, verifier, err := generatePKCECodeChallenge()
if err != nil {
log.Fatalf("could not generate PKCE challenge: %v", err)
}

token, err := config.Exchange(
context.Background(),
AuthorizationCode,
oauth2.SetAuthURLParam("code_verifier", verifier))
if err != nil {
log.Fatalf("could not exchange Authorization Code: %v", err)
}

log.Printf("Access Token: %s", token.AccessToken)
log.Printf("Expires: %s", token.Expiry.String())
}