Further Reading
OIDC Explainer
The following diagram outlines the general authentication flow for an integrating app:
Registration
Before OIDC authentication can take place, developers must register their applications with Worldcoin. This is a one-time action. There are two ways to accomplish this:
- Create a new application on the Developer Portal.
- Use the
/register
endpoint, request body details can be found here.
During registration, you will need to provide the following values:
redirect_uris
: Required, list of approved websites the user can be redirected to after successful authentication.client_name
: Optional, the name of the application that's displayed to usersapplication_type
: Optional, one of "web" or "mobile". Defaults to "web"grant_types
: Optional, the type of flows this application will use. Can include "authorization_code", "implicit", or "hybrid". Defaults to "authorization_code"response_type
: Optional, the response type expected by the application. Can include any of "code", "token", or "id_token". Defaults to "code"code
: Recommended for most applications. The/authorize
endpoint will include an authorization code that can be exchanged for an access token and/or ID token on the/token
endpoint. Best suited for web/mobile applications with dedicated backends, where security is the highest priority.token
: The/authorize
endpoint will include an access token, which can be used to fetch user information from the/userinfo
and/introspect
endpoints. Best suited for low-risk applications, and client-only/SPAs where aclient_secret
cannot be concealed.id_token
: The/authorize
endpoint will include a signed JWT containing information about the user, including the uniquesub
claim (otherwise known as the nullifier hash). Provides simple user authentication, while keeping the amount of user data shared to a minimum. Best for privacy-conscious apps.
All redirect URIs must be over HTTPS, and contain no port numbers or URL fragments. For example, https://app.example.com/login
is valid, but https://app.example.com:3000/login
is not. Similarly, https://app.example.com/login#foo
is not valid, but https://app.example.com/login?foo=bar
is.
After registration is complete, you will have a valid app_id
that will be needed for every other step in the authentication process. This value is equivalent to client_id
from the OIDC specification
Flows
World ID supports the authorization code, implicit, and hybrid flows from the OIDC spec. Applications can use any one of these flows to authenticate users.
Generally, applications should implement the authorization code flow, as it is more secure than the implicit flow. Applications without backend servers (that may be running purely client-side) are more suited to implicit authentication.
Authentication
Authentication begins with a request to the /authorize
endpoint.
When using the native Sign In with Worldcoin page, most of the OIDC process is handled for you. You can begin the authentication cycle by redirecting your users to:
https://id.worldcoin.org/authorize?client_id={app_id}&response_type={code|token|id_token}&redirect_uri={encoded_redirect_url}&scope={scope}&state={state_value}&nonce={nonce_value}
Example values could be:
client_id
: obtained from the Developer Portal or/register
endpoint (example:app_lshSNnaJfdt6Sohu6YAA
).response_type
: response type as specified in OIDC spec, remember to URL encode (example:code%20id_token
).redirect_uri
: where the user is redirected upon successful authentication. Must be on the approved redirect URI list which can always be updated in the Developer Portal (example:https%3A%2F%2Fapp.example.com%2Flogin
).scope
: space-separated list of scopes to request. Defaults toopenid
if not provided. (example:openid%20profile%20email
).state
: unique value used to track a user's session (example:session_102030405060708090
).nonce
: random value to prevent replay attacks (example:z-dkEmoy_ujfk7B8uTiQpp
). Required when using theid_token
response type.
The user will then authenticate with their World ID via the World app. Once successfully authorized, the user is redirected back to your application. The redirect URL will contain a number of values, depending on the flow you are using.
Redirect Responses
If using the default authorization code flow, the redirect URL will contain the following params:
code
: An authorization code that can be exchanged for an ID tokenstate
: The optional state value passed to the/authorize
endpoint
If you received a response containing an authorization code, you must exchange it for an ID token on the /token
endpoint. Request details can be seen here.
If using implicit flow, the redirect URL will contain the following params:
id_token
: A signed JWT identifying the user, and any requested scope information
nonce
within the ID token matches the nonce you provided.To verify an ID token, fetch the public key from the /jwks
endpoint. You can read more about this process at the Auth0 blog or JWT.io, but one example method could be:
import * as jose from 'jose'
const verifyJwt = (token: string) => {
const JWKS = jose.createRemoteJWKSet(new URL('https://id.worldcoin.org/jwks.json'))
const { payload, header } = await jose.jwtVerify(token, JWKS, {
issuer: 'https://id.worldcoin.org',
aud: 'app_lshSNnaJfdt6Sohu6YAA',
})
return payload
}
verifyJwt('eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp.eyAs.XVCJ9...')