Skip to content

Quickstart (5 minutes)

This assumes the managed IdP at https://1pass.dev. For self-hosting, see self-hosting.

Prerequisites

bash, curl, openssl, python3.

1. Create an account

https://start.1pass.dev/console/signup → email + password.

Email verification required before registering an app (RP)

Before you can register an app (RP) in the developer console, you must verify your email. After signing up, click the link in the verification email, or resend it from the console at /account. Registration is blocked until you verify. → App registration guide · Prerequisite

2. Register an OAuth app

At https://start.1pass.dev/developer/applications/new:

  • Redirect URI: http://localhost:4000/auth/callback
  • Client type: Confidential (you have a backend) / Public (mobile, SPA, or standalone CLI)

Right after you save, the client_secret is shown only once — store it in .env immediately. If you lose it, you can only re-issue a new one.

App detail → Manage Scopes → enable openid, profile:basic, and email.

If you need an id_token, openid is required

Reading identity straight from the id_token payload (common in SPAs and serverless) requires the openid scope. Without it, the token response omits the id_token, and identity can only be retrieved via userinfo. profile is an alias for profile:basic, but standardize on profile:basic for both registration and requests. — Scope reference

Deciding the client type: Public vs Confidential.

3. Environment variables

bash
export LOGI="https://api.1pass.dev"
export CLIENT_ID="logi_..."
export CLIENT_SECRET="..."         # omit for a Public client
export REDIRECT="http://localhost:4000/auth/callback"

Endpoint discovery: $LOGI/.well-known/openid-configuration.

4. Generate a PKCE pair

bash
VERIFIER=$(openssl rand -hex 32)

CHALLENGE=$(printf '%s' "$VERIFIER" \
  | openssl dgst -sha256 -binary \
  | python3 -c 'import sys,base64; print(base64.urlsafe_b64encode(sys.stdin.buffer.read()).rstrip(b"=").decode())')

echo "verifier  = $VERIFIER"
echo "challenge = $CHALLENGE"

5. Get an Authorization Code

bash
open "$LOGI/oauth/authorize?\
client_id=$CLIENT_ID&\
redirect_uri=$REDIRECT&\
response_type=code&\
scope=openid+profile:basic+email&\
state=random_xyz&\
code_challenge=$CHALLENGE&\
code_challenge_method=S256"

http://localhost:4000/auth/callback?code=...&state=random_xyz. Copy the code value.

Show only specific login methods on the login screen

If you want to surface only specific login methods — for example, you use Google Workspace exclusively across the company — add a provider parameter to the authorize URL (e.g. &provider=google shows only the "Continue with Google" button). You can also enforce this per app in the console. For the full behavior, see login method restriction.

6. Exchange for tokens

bash
CODE="the_code_you_copied"

curl -s -X POST "$LOGI/oauth/token" \
  -d grant_type=authorization_code \
  -d code=$CODE \
  -d redirect_uri=$REDIRECT \
  -d code_verifier=$VERIFIER \
  -d client_id=$CLIENT_ID \
  -d client_secret=$CLIENT_SECRET

Public client: remove the -d client_secret=... line. Sending it triggers an invalid_client rejection.

bash
curl -s -X POST "$LOGI/oauth/token" \
  -d grant_type=authorization_code \
  -d code=$CODE \
  -d redirect_uri=$REDIRECT \
  -d code_verifier=$VERIFIER \
  -d client_id=$CLIENT_ID

Response:

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "DWxB...",
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...",
  "scope": "openid profile:basic email"
}

The id_token is included only when you requested the openid scope.

7. Look up identity — two ways

7a. Read sub from the id_token (no re-verification of the signature)

If you received the /oauth/token response directly over TLS, you can trust the sub in the id_token payload right away. Note that the id_token carries only the standard OIDC claims like sub — it does not include email or name.

bash
echo "$ID_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# → {"iss":"logi","sub":"1","aud":"logi_...","exp":...,"iat":...,"at_hash":"..."}

If you received it straight from the token endpoint, re-verifying the signature is optional

An id_token received directly over TLS from /oauth/token within the same backend request can be trusted at the payload level (OIDC §3.1.3.7 #6 exception). Verifying the signature against JWKS is required only when the id_token arrives over an untrusted path (front-channel, stored and reused, or relayed). → JWKS verification

7b. Get the profile (email, name) from userinfo

Profile fields like email and name are not in the id_token, so call userinfo with the access_token.

bash
ACCESS_TOKEN="access_token_from_the_response_above"
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" "$LOGI/oauth/userinfo"
# → {"sub":"1","nickname":"Gildong","name":"Hong Gildong","email":"user@example.com","email_verified":true}

Troubleshooting

  • invalid_client: a Public client sent a client_secret — remove the line.
  • PKCE: S256 is required, plain is rejected. redirect_uri allows only https / 127.0.0.1 / localhost / custom-scheme.

Next steps

Identity가 제품의 신뢰를 만듭니다.