Roles and responsibilities
- Turnkey: runs verifiable infrastructure to create credentials and verify OIDC tokens
-
Parent: that’s you! For the rest of this guide we’ll assume you, the reader, are a Turnkey customer. We assume that you have:
- an existing Turnkey organization (we’ll refer to this organization as “the parent organization”)
- a web application frontend (we’ll refer to this as just “app” or “web app”)
- a backend able to sign and POST Turnkey activities (“backend” or “parent backend”)
- End-User: the end-user is a user of your web app. They have an account with Google.
- OIDC Provider: a provider able to authenticate your End-Users and provide OIDC tokens as proof. We’ll use Google as an example.
OAuth step-by-step
Registration (signup)

- End-User enters the signup flow on the app, gets redirected to Google for authentication.
- Upon completion, the Parent’s backend receives the OIDC token authenticating End-User.
- This token is used inside of a
CREATE_SUB_ORGANIZATION
activity to register Google as the Oauth provider under the root user. - Turnkey verifies the OIDC token and creates a new sub-organization.
issuer
is set tohttps://accounts.google.com
audience
is set to<google-oauth-app-id>
(your Oauth app ID)subject
is set<google-end-user-id>
(the user ID ofEnd-User
on Google’s side)
Authentication (login)

- End-User enters the login flow on the app, gets redirected to Google for authentication.
- Upon completion,
Parent backend
receives the OIDC token authenticating End-User. - This token is used inside of an
OAUTH
activity, signed by the Parent’s backend. - Turnkey verifies the OIDC token and encrypts an expiring API key credential to End-User.
- End-User decrypts the credential.
OIDC token verification
All OIDC tokens are verified inside of Turnkey’s secure enclaves. We’ve designed a new secure enclave to fetch TLS content securely and bring non-repudiation on top of TLS content: our TLS fetcher returns a URL and the fetched content, signed by the TLS fetcher’s quorum key. By trusting the TLS fetcher quorum key, other Turnkey enclaves can bring TLS-fetched data into their computation safely. Verifying OIDC token is the first computation which requires this! To verify an OIDC token, other Turnkey enclaves receive the OIDC token as well as:- the signed content of the issuer’s OpenId configuration. OpenId configuration must be hosted under
/.well-known/openid-configuration
for each domain. For Google for example, the issuer configuration is ataccounts.google.com/.well-known/openid-configuration
. This JSON document contains, among other thing, ajwksUri
key. The value for this key is a URL hosting the list of currently-valid OIDC token signers. - the signed content of the issuer’s
jwksUri
(e.g., for Google, thejwksUri
isgoogleapis.com/oauth2/v3/cert
). This is a list of public keys against which the secure enclave can verify tokens. Note: these public keys rotate periodically (every ~6hrs), hence it’s not possible to hardcode these public keys in our secure enclave code directly. We have to fetch them dynamically!
iss
, aud
and sub
attributes against the registered OAuth providers on the Turnkey sub-organization. We also check exp
to make sure the OIDC token is not expired, and the nonce
attribute (see next section).
Nonce restrictions in OIDC tokens
OurOAUTH
activity requires 2 parameters minimum:
oidcToken
: the base64 OIDC tokentargetPublicKey
: the client-side public key generated by the user
nonce
claim is set to sha256(targetPublicKey)
.
For example, if the iframe public key is 04bb76f9a8aaafbb0722fa184f66642ae425e2a032bde8ffa0479ff5a93157b204c7848701cf246d81fd58f6c4c47a437d9f81e6a183042f2f1aa2f6aa28e4ab65
, our enclaves expect the OIDC token nonce to be 1f9570d976946c0cb72f0e853eea0fb648b5e9e9a2266d25f971817e187c9b18
.
This restriction only applies during authentication (OAUTH
activity). Registration via CREATE_OAUTH_PROVIDER
and CREATE_SUB_ORGANIZATION
activities is not affected since these activities do not accept a targetPublicKey
and do not return encrypted credentials as a result.
If your OAuth provider does not allow you to customize nonce
claims, Turnkey also accepts and validates tknonce
claims. This is an alternative claim that will be considered. Only one of (nonce
, tknonce
) needs to be set to sha256(targetPublicKey)
; not both.
OAuth vs. OIDC
OAuth2.0 is a separate protocol from OIDC, with distinct goals:- “OAuth2.0” is an authorization framework
- “OIDC” is an authentication framework
Providers
Below, some details and pointers about specific providers we’ve worked with before. If yours isn’t listed below it does not mean it can’t be supported: any OIDC provider should work with Turnkey’s OAuth.
Apple
Apple integration is also extensively tested and supported, and is integrated into our demo wallet (hosted at https://wallet.tx.xyz). The code provides an example component as well as an example redirect handler. Documentation for Apple OIDC can be found here.- You will need to generate a code verifier that can either be recalled (e.g. from a database) or reassembled in a later request.
- You will need to provide a code challenge as a parameter of the OAuth redirect that is either the code verifier itself or the hash of the code verifier.
- Instead of receiving the OIDC token after the OAuth flow, you will receive an auth code that must be exchanged for an OIDC token in a subsequent request. The code verifier and your app’s ID are also required in this exchange.

Auth0
This provider was tested successfully and offers a wide range of authentication factors and integration. For example, Auth0 can wrap Twitter’s auth or any other “Social Connection”. In the testing process we discovered that Auth0 admins can manage users freely. Be careful about who can and can’t access your Auth0 account: Auth0’s management APIs allow for account merging. Specifically, anyone with ausers:update
scope token can call this endpoint to arbitrarily link an identity.
For example, if a Google-authenticated user (OIDC token sub
claim: google-oauth2|118121659617646047510
) gets merged into a Twitter-authenticated user (OIDC token sub
claim: twitter|47169608
), the OIDC token obtained by logging in through Google post-merge will be twitter|47169608
. This can be surprising and lead to account takeover if an Auth0 admin is malicious. This is documented in Auth0’s own docs, here.
AWS Cognito
The main thing to call out is the inability to pass customnonce
claims easily. To pass the hash of the end-user’s iframe public key, use a custom tknonce
claim instead.