Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

How to configure Auth0 with AWS AppSync

(Read this article on the blog)

OpenID Connect with AppSync

AppSync supports multiple types of authorization providers, and one of them is Openid Connect. It is an open standard and many user directories support it. Using that, you can integrate third-party login providers with an AppSync API.

How does it work?

Users are in the third-party system that handles authentication (logging in) and issues authentication tokens. Then when the user makes a request to AppSync they include this Token. AppSync verifies that it is not forged and it indeed came from the OpenID Connect provider. The token contains information about the user, most importantly its identifier that resolvers in AppSync can use. As a result, what you can do with Cognito you can also configure for many other providers.

In this article we’ll look into how to integrate Auth0 with AppSync. We’ll have users in an Auth0 tenant, and call an AppSync API with tokens issued by that tenant. Then we’ll also see what AppSync resolvers see when a client uses a third-party token.

Auth0userAppSync APIlogintokenquerytokenresponseUsing an external user directory with AppSync

Auth0 config

The first step is to configure an application on Auth0. This is where users can log in:

OAuth supports several ways to implement the login flow, but the most useful is based on a redirect to the auth endpoint and then a code parameter that is then exchanged for the token. This is roughly the same as for Cognito, described in this article.

This needs a callback URL, then I needed to disable the token endpoint authentication as the SPA has no access to the client secret:

Then the last thing is to have some users:

Terraform

Since Auth0 supports Terraform, it is easy to wire everything together with code:

resource "auth0_client" "appsync" {
	name            = "Appsync-test-${random_id.id.hex}"
	app_type        = "spa"
	callbacks       = ["https://${aws_cloudfront_distribution.distribution.domain_name}"]
	oidc_conformant = true
	token_endpoint_auth_method = "none"

	jwt_configuration {
		alg = "RS256"
	}
}

resource "auth0_user" "user1" {
  connection_name = "Username-Password-Authentication"
  email = "[email protected]"
  email_verified = true
  password = "Password.1"
}

AppSync

Now that there is a configured user directory with some users, the next thing is to configure the API. This part is rather simple, as AppSync only needs the domain:

While the client ID is optional, you’ll need that on the client-side as it is a required parameter for most calls.

Why a domain is enough

AppSync validates the token, but why it only needs the auth domain? Validation needs a public key to check the signature, but the configuration does not need it. Where does is come from?

OpenID Connect specifies a location with all the necessary information. This is at https:///.well-known/openid-configuration and it is a JSON containing several fields:

{
	"issuer": "https://dev-at4in79i.us.auth0.com/",
	"authorization_endpoint": "https://dev-at4in79i.us.auth0.com/authorize",
	"token_endpoint": "https://dev-at4in79i.us.auth0.com/oauth/token",
	"userinfo_endpoint": "https://dev-at4in79i.us.auth0.com/userinfo",
	"jwks_uri": "https://dev-at4in79i.us.auth0.com/.well-known/jwks.json",
	...,
}

Notice the jwks_uri, which is a link to another JSON:

{
	"keys": [
		{
			"alg": "RS256",
			"kty": "RSA",
			"use": "sig",
			"n": "rgxLjmjj_...",
			"e": "AQAB",
			"kid": "eUhhBOwRy_...",
			"x5t": "SEmMAyXE3H...",
			"x5c": [
				"MIIDDTCCAfWgAwIBA..."
			]
		},
		...
	]
}

This contains a list of keys, identified by the kid (key ID). The token also has a kid. When AppSync validates the token it fetches the JWKs, find the matching key, then verify the signature using the parameters.

AWS documentation has an article that describes it for Cognito, but the idea is the same for other providers.

Client-side

The client-side wires the two services together. The browser redirects to Auth0 for login, where the login flow kicks in. This is where a username, a password, MFA, and any other information is taken from the user that is needed for logging in.

When Auth0 is happy with the answers, it redirects to the SPA with a code parameter. Finally, the client exchanges this code for an id_token:

The exact flow is a bit more complicated as there are several parameters required on every step for it to work. Check out this article for a more in-depth analysis.

The id_token is what AppSync needs in the authorization header:

Under the hood, this is where AppSync does the token validation using the JWKs, and then it calls the resolvers.

Resolver-side

The $context.identity provides information about the user:

{
	"claims": {
		"sub": "auth0|62134bfe5ac54f0069f299c7",
		"aud": "UinUoTppV0jjuSbGJlkcC9UMH9DIH8SV",
		"iss": "https://dev-at4in79i.us.auth0.com/",
		"exp": 1645470280,
		"iat": 1645434280
	},
	"issuer": "https://dev-at4in79i.us.auth0.com/",
	"sub": "auth0|62134bfe5ac54f0069f299c7"
}

The sub is the ID of the user in Auth0. Usually, the API can use this to store and retrieve data for this user.

Conclusion

OpenID Connect provides a standards-based way to wire a third-party authentication provider with AppSync. With a few lines of configuration, you can use any compliant user directory with an API.



This post first appeared on Blog - Advanced Web Machinery, please read the originial post: here

Share the post

How to configure Auth0 with AWS AppSync

×

Subscribe to Blog - Advanced Web Machinery

Get updates delivered right to your inbox!

Thank you for your subscription

×