Docs menu

Quickstart

Register an app, get credentials and run the code flow with PKCE.

This page runs the whole flow with curl and a shell, so you see every request. The framework guides do the same in code.

1. Register an app

  1. Sign in and create an organization. Any PulseID account can.
  2. In the organization, register an app: a name, a kind, a homepage URL and at least one redirect URI. Use web when your server can keep a secret. Use public for an app that cannot, such as a single-page or native app.
  3. Copy the client ID, which starts with app_. A web app also gets a client secret, which starts with psk_. It is shown once, when the app is created. If you lose it, rotate it (see Secrets). A public app has no secret.

Redirect URIs must be https, with no fragment and no wildcard, and each is matched as you registered it. PulseID does not accept http://localhost URIs, so develop behind an https address, for example a tunnel or a local certificate. An organization may have 25 apps and an app 10 redirect URIs.

2. Find the endpoints

PulseID publishes its endpoints and keys in the discovery document. Read it at startup rather than hard-coding the URLs.

Discovery
curl -s https://id.warpulse.com/.well-known/openid-configuration

https://id.warpulse.com/.well-known/openid-configuration

3. Make a code verifier and challenge

PKCE S256 is required for every app, public or web. Make a random verifier for each sign-in, keep it on your server with the sign-in attempt, and send only its SHA-256 challenge.

PKCE
CODE_VERIFIER=$(openssl rand -base64 48 | tr '+/' '-_' | tr -d '=\n')
CODE_CHALLENGE=$(printf %s "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')

4. Send the person to PulseID

Redirect the browser to https://id.warpulse.com/auth with these parameters.

Authorization request parameters
ParameterExample valueNotes
response_typecodeThe code flow is the only one PulseID has.
client_idYOUR_CLIENT_IDThe app id from the portal.
redirect_urihttps://app.example.com/auth/callbackOne of the redirect URIs you registered, exactly.
scopeopenid profile email offline_accessOnly what your app needs.
stateRANDOM_STATEA random value you check when the person comes back.
nonceRANDOM_NONCEA random value you check in the ID token.
code_challengeBASE64URL_SHA256_OF_VERIFIERThe PKCE challenge, made from your code verifier.
code_challenge_methodS256PKCE S256 is required. There is no plain method.
promptconsentNeeded to receive offline_access.
Authorization URL
https://id.warpulse.com/auth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fapp.example.com%2Fauth%2Fcallback&scope=openid%20profile%20email%20offline_access&state=RANDOM_STATE&nonce=RANDOM_NONCE&code_challenge=BASE64URL_SHA256_OF_VERIFIER&code_challenge_method=S256&prompt=consent

offline_access and prompt=consent go together: send prompt=consent whenever you ask for offline_access. Ask for offline_access only to receive a refresh token. A refresh token goes to a verified web app only. An unverified app never gets a refresh token. A public app never gets a refresh token either, even when its organization is verified. In both cases PulseID removes offline_access from the request without an error. If you do not need a refresh token, use the scope openid profile email and leave out prompt.

The first time a person signs in to your app they see a consent screen that names your organization. For an unverified organization it also says that WarPulse has not verified the app and shows your homepage address.

5. Handle the return

The person comes back to your redirect URI with code and state. Check that state is the one you sent. The code works once and for 60 seconds, so exchange it at once.

6. Exchange the code for tokens

A web app authenticates with its client ID and secret over HTTP Basic. A public app sends its client ID and the verifier only.

Token request, web app
curl -X POST https://id.warpulse.com/token \
  --user "$CLIENT_ID:$CLIENT_SECRET" \
  --data-urlencode grant_type=authorization_code \
  --data-urlencode "code=$CODE" \
  --data-urlencode "redirect_uri=$REDIRECT_URI" \
  --data-urlencode "code_verifier=$CODE_VERIFIER"
Token request, public app
curl -X POST https://id.warpulse.com/token \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode grant_type=authorization_code \
  --data-urlencode "code=$CODE" \
  --data-urlencode "redirect_uri=$REDIRECT_URI" \
  --data-urlencode "code_verifier=$CODE_VERIFIER"

The answer holds an id_token, an access_token (opaque, for https://id.warpulse.com/me, good for 10 minutes) and, for a verified web app that asked for offline_access, a refresh_token.

7. Check the ID token

Before you trust it, check its signature against the keys at https://id.warpulse.com/jwks, and check that iss is https://id.warpulse.com, aud is your client ID, exp is in the future and nonce is the one you sent. Then sub is the person. Use it as your key for that person. See the reference for the claims.

8. Refresh

If you have a refresh token, trade it for new tokens before they run out. Every use returns a new refresh token and ends the old one. Store the new one. A refresh token lasts 30 days at the most from the sign-in it came from.

Refresh request
curl -X POST https://id.warpulse.com/token   --user "$CLIENT_ID:$CLIENT_SECRET"   --data-urlencode grant_type=refresh_token   --data-urlencode "refresh_token=$REFRESH_TOKEN"