To use YouVersion sign-in from an app or web page, the easiest way to do so is to use our SDKs instead of using the information on this page. This guide walks through the YouVersion OAuth authorization code flow using PKCE, which can be a challenging task and is intended for developing new SDKs or situations where our existing SDKs don't support your tech stack or feature needs.
Pre-auth: Retrieve your app_key
First, create your developer account and register your application at platform.YouVersion.com to obtain an App Key.
- Create a new App
- Set the
callback url - Upon creation, note the
app_key. This will be the oauthclient_id
Auth Call 1: /authorize
This initiates the auth flow for the end user, who will be redirected to login.youversion.com and, after signing in there, be presented with scopes ("YouVersion wants to share your email with App XYZ").
ANDROID DEVS - Android requires in-browser "user interaction" for authorization to complete. You will need to additionally add param require_user_interaction=true to this call, which will prompt the user to click a continuation button after each login.
Endpoint URL
Code
Query Parameters
| Parameter | Description |
|---|---|
response_type | code |
client_id | Your app's client ID from the Platform Portal (the app_key) |
redirect_uri | Your app's callback URL (must match the one registered in the Platform Portal) |
scope | Space-separated list of requested scopes (e.g., openid profile email) |
nonce | Random string for replay protection (generate a unique value per request) |
state | Random string for CSRF protection (generate a unique value per request) |
code_challenge | Base64 URL-encoded SHA256 hash of the code_verifier (for PKCE) |
code_challenge_method | S256 (indicates SHA256 hashing) |
require_user_interaction | true Optional param for Android and any platform that requires user interaction to continue sign-in flows |
Example Request URL
Code
Redirect back to client
After the user successfully authenticates and grants consent, they will be redirected (303) back to your App's callback URL with the following query parameters:
| Parameter | Description |
|---|---|
yvp_id | The user's unique YouVersion Platform ID (UUID) |
state | The same state value you provided in the original request (for CSRF validation) |
user_name | The user's display name |
profile_picture | URL to the user's profile picture (via YouVersion image proxy) |
user_email | The user's email address |
Example Redirect URL
Code
Auth Call 2: /callback
After receiving the redirect from step 2, your client app should make a request to the /callback endpoint with the user information received. This data will be used to mint a token for the final step.
Endpoint URL
Code
Query Parameters
| Parameter | Description |
|---|---|
state | The same state value from the previous steps (for validation) |
yvp_id | The user's unique YouVersion Platform ID (from the redirect) |
user_name | The user's display name (from the redirect) |
profile_picture | URL to the user's profile picture (from the redirect) |
user_email | The user's email address (from the redirect) |
Example Request URL
Code
Response
The server will respond with a redirect (302) to your callback URL with the authorization code:
Code
Response Parameters:
code: The authorization code to exchange for tokensscope: The granted scopesstate: Your originalstatevalue for validation
Auth Call 3: /token
Exchange the authorization code from step 3 for access tokens. This is a server-to-server POST request.
Endpoint URL
Code
Request Body Parameters
| Parameter | Description |
|---|---|
grant_type | authorization_code (OAuth 2.0 grant type) |
code | The authorization code received in step 3 |
redirect_uri | Must match the redirect_uri from step 2 |
client_id | Your app's client ID (the app_key) |
code_verifier | The original PKCE code verifier (before hashing for code_challenge) |
Example Request
Code
Response
The server responds with a JSON object containing the access tokens:
Code
Response Fields:
access_token: The OAuth 2.0 access token (JWT - use in API requests withAuthorization: Bearerheader)token_type: AlwaysBearerexpires_in: Token lifetime in seconds (typically 3599 = ~1 hour)refresh_token: Token to obtain a new access token when it expiresid_token: OpenID Connect ID token (JWT containing user claims like email, name, etc.)scope: The granted scopes
Note: Both
access_tokenandid_tokenare JSON Web Tokens (JWTs). You can decode them at jwt.io to inspect their claims, but always verify signatures in production.
Post-auth: Extracting user info from the JWT tokens
Once you have the tokens from step 4, you can decode the JWTs to access user information and claims.
Decoding JWTs
To decode and verify JWTs, use a JWT library for your programming language:
- JavaScript/Node.js:
jsonwebtoken,jose - Python:
PyJWT,python-jose - Ruby:
jwt - Go:
golang-jwt/jwt - Java:
java-jwt,jjwt - .NET:
System.IdentityModel.Tokens.Jwt
Important: Always verify the JWT signature using the public keys from the YouVersion JWKS endpoint before trusting the claims.
Access Token Claims
The access_token contains user information and authorization details. When decoded, it will look like this:
Code
Key Claims:
| Claim | Description |
|---|---|
yvp_id | The user's unique YouVersion Platform ID - use this as the primary user identifier |
sub | Subject - also contains the user's unique ID (same as yvp_id) |
email | The user's email address |
name | The user's display name |
profile_picture | URL to the user's profile picture |
aud | Audience - your app's client ID (validates the token is for your app) |
iss | Issuer - the YouVersion API endpoint that issued the token |
exp | Expiration time (Unix timestamp) |
iat | Issued at time (Unix timestamp) |
nonce | The nonce value from your original request (for replay protection) |
jti | JWT ID - unique identifier for this token |
Best Practice: Use
yvp_idas the primary key when storing user information in your database. This ID is stable and unique for each user.
Best Practices and Resources
Security
PKCE Implementation
- Generate secure random values: Use cryptographically secure random generators for
code_verifier(43-128 characters) - Never reuse code verifiers: Generate a new one for each authorization flow
- Store code_verifier securely: Keep it in memory or secure storage until token exchange
State and Nonce
- Always validate state: Verify the returned
statematches what you sent to prevent CSRF attacks - Use unique values: Generate a new
stateandnoncefor every authorization request - Store temporarily: Associate
statewith the user's session and validate on callback
Token Security
- Verify JWT signatures: Always validate tokens using the JWKS endpoint before trusting claims
- Store tokens securely: Use secure storage (e.g., HTTP-only cookies, encrypted storage) - never in localStorage for web apps
- Never log tokens: Avoid logging access tokens or refresh tokens in production
Token Management
Access Token Usage
- Include in API requests: Send as
Authorization: Bearer {access_token}header - Check expiration: Tokens typically expire in 1 hour - implement refresh logic before expiration
- Handle 401 errors: When an API returns 401, refresh the token and retry
Refresh Tokens
- Store securely: Refresh tokens are long-lived and sensitive
- Implement refresh flow: Use refresh tokens to obtain new access tokens without re-authenticating the user
- Revoke on logout: Call the token revocation endpoint when users log out
User Data
User Identification
- Use
yvp_idas primary key: Always useyvp_id(not email) as the stable user identifier in your database - Don't assume email uniqueness: Users can change emails, so don't rely on email as a primary key
- Update user info on login: Refresh user profile data (name, email, picture) on each login to stay current
Privacy
- Request minimum scopes: Only request the scopes your app actually needs
- Don't share user data: Never share user data with third parties without explicit consent
Testing and Production
- Test thoroughly: Test the complete flow including error cases (denied consent, expired tokens, network failures)
Error Handling
- Handle user denial: Gracefully handle when users decline to authorize your app
- Implement retry logic: Network requests can fail - implement exponential backoff
- Log errors (not tokens): Log error messages and codes, but never log tokens or sensitive data
Resources
Documentation
- OAuth 2.0 RFC 6749 - OAuth 2.0 specification
- PKCE RFC 7636 - Proof Key for Code Exchange specification
- OpenID Connect - OpenID Connect specification
- JWT.io - JWT decoder and debugger
Libraries
- JavaScript:
@auth0/auth0-spa-js,oidc-client-js - Python:
authlib,python-jose - Ruby:
omniauth-oauth2 - Go:
golang.org/x/oauth2 - Java/Kotlin:
AppAuth-Android - Swift:
AppAuth-iOS(but, using our Swift SDK would be easiest.)