Integrate

Sign in with UC Card

Let users sign in to your website or app with their UC Card account, using OAuth 2.0 and OpenID Connect.

Sign in with UC Card lets users sign in to your website or app with their existing UC Card account, so they don't need to create another username and password.

UC Card is an OpenID Connect (OIDC) provider built on OAuth 2.0. As a UC Card Partner, you add a Continue with UC Card button to your sign-in page and use the standard authorization code flow with PKCE. Any certified OIDC library works.

When a user signs in and approves your app, you receive:

  • An ID token: a signed JWT (RS256) that identifies the user by sub. The sub never changes for that user and is unique to your developer account.
  • Profile claims such as name and picture, only for the scopes the user approves.
  • An access token for the user info endpoint, and a refresh token if you request offline_access.

You can offer Sign in with UC Card on its own or alongside your existing sign-in methods. It's also required for payments, which identify users by their sub.

How it works

UC Card PartnerUC CardContinue with UC CardButton on your login pageSign in & approve/oauth2/authorize · PKCEExchange codeYour /callback routeIssue tokens/oauth2/token · id_tokenSigned inFind or create user by subaccess_deniedShow your login page againRedirect?code & statePOST + code_verifiersubUser cancels
  1. The user clicks Continue with UC Card on your login page.
  2. Your server redirects them to UC Card. They sign in with their UC Card account (or are already signed in) and approve your app.
  3. UC Card redirects back to your redirect_uri with a one-time code.
  4. Your server exchanges the code for tokens and reads the user's sub from the id_token.
  5. You find or create the user in your database by sub and start your own session.

Users need a UC Card account

Only people with a UC Card account can use this button. Keep your other login options for everyone else, or tell users they can create an account in the UC Card App.

Before you start

Create an app in the console

In the Developer Console, create an app (see Console setup). You get a client_id, and a client_secret for server-side apps.

Register your redirect URIs

Add every callback URL exactly, for example https://partner.example.com/auth/uccard/callback. UC Card only redirects to registered URIs.

Add test users

New apps are in sandbox: only you and up to 20 test users can sign in until the app is reviewed and published.

Design guidelines

Put a Continue with UC Card button on your sign-in and sign-up pages. It links to a route on your server that starts the sign-in flow (below, /auth/uccard/login). Get the HTML and CSS from the Sign-in button generator.

The mockups show how the button should look on a UC Card Partner website, on desktop and mobile, and what the user sees after tapping it.

🔒 partner.example.com/login
UC Card PartnerProductsPricingSupport

Welcome back

Sign in to your account.

Email
Password
Sign in
or
Continue with Card

You'll continue to UC Card to sign in.

New here? Create account

1Partner website · desktop
Place the button under your own sign-in form, separated by “or”, at the same width.
UC Card Partner

Welcome back

Sign in to your account.

Email
Password
Sign in
or
Continue with Card

You'll continue to UC Card to sign in.

New here? Create account

2Partner website · mobile
Full-width button within thumb reach. Keep the hint line under it.

UC Card Partner wants to access your UC Card account

This will allow UC Card Partner to:

  • See your name and profile photo
  • Use a unique ID to recognize you
Continue
Cancel

🔒 UC Card never shares your password or payment PIN.

By continuing you agree to UC Card Partner’s Privacy Policy and Terms.

3UC Card sign-in · mobile
What the user sees next: the UC Card card shows your app name, logo and requested data.
Do Don't
Put the button on both the sign-in and sign-up screens Hide it behind a "More options" link
Separate it from your own form with an "or" divider Place it inside or above your password fields
Make it the same width as your own sign-in button Make it smaller than other login buttons
On mobile, use full width and keep it within thumb reach Put it below the fold on small screens
Keep the hint "You'll continue to UC Card to sign in." Say "Sign in with HTP" or any other name. It's always UC Card
Upload your app name and logo in the console: they appear on the UC Card card (step 3) Use a logo or name that differs from your website

Your app name and logo on the UC Card card

The UC Card sign-in card shows the app name, logo and requested data from your console app profile. Changing them on a published app needs another review.

Server integration

Any certified OpenID Connect library works. Point it at the discovery URL and it finds every endpoint. Here's a complete Node.js (Express) example using openid-client v6. It handles PKCE, state, nonce and ID token validation for you.

server.js
import express from 'express';
import session from 'express-session';
import * as client from 'openid-client';

const config = await client.discovery(
  new URL('https://auth.htp.example'),
  process.env.UCCARD_CLIENT_ID,
  process.env.UCCARD_CLIENT_SECRET,
);
const REDIRECT_URI = 'https://partner.example.com/auth/uccard/callback';

const app = express();
app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false }));

// 1. The button links here
app.get('/auth/uccard/login', async (req, res) => {
  const verifier = client.randomPKCECodeVerifier();
  req.session.oidc = { verifier, state: client.randomState(), nonce: client.randomNonce() };
  const url = client.buildAuthorizationUrl(config, {
    redirect_uri: REDIRECT_URI,
    scope: 'openid profile',
    code_challenge: await client.calculatePKCECodeChallenge(verifier),
    code_challenge_method: 'S256',
    state: req.session.oidc.state,
    nonce: req.session.oidc.nonce,
  });
  res.redirect(url.href);
});

// 2. UC Card redirects back here
app.get('/auth/uccard/callback', async (req, res) => {
  const { verifier, state, nonce } = req.session.oidc ?? {};
  const tokens = await client.authorizationCodeGrant(config, new URL(req.originalUrl, 'https://partner.example.com'), {
    pkceCodeVerifier: verifier,
    expectedState: state,
    expectedNonce: nonce,
  });
  const claims = tokens.claims(); // validated id_token
  const user = await db.users.findOrCreateBySub(claims.sub, { name: claims.name, picture: claims.picture });
  delete req.session.oidc;
  req.session.userId = user.id;
  res.redirect('/');
});

Other languages

Use any OIDC-certified library: Authlib (Python), coreos/go-oidc + golang.org/x/oauth2 (Go), league/oauth2-client (PHP), Spring Security OAuth2 Client (Java), AppAuth (iOS/Android). Configure it with the discovery URL, your client_id/client_secret and PKCE S256.

Endpoints

Use discovery to configure your OIDC library:

http
GET https://auth.htp.example/.well-known/openid-configuration
Purpose Path
Authorization /oauth2/authorize
Token /oauth2/token
User info /oauth2/userinfo
JWKS /oauth2/jwks
Revoke /oauth2/revoke

Authorization code flow with PKCE S256 (required for SPA/native, recommended for web). ID tokens are signed RS256. Client authentication: client_secret_basic (recommended), client_secret_post, or none for public clients.

Scopes

Scope Claims
openid (required) sub
profile name, given_name, family_name, nickname, picture, gender, birthdate, updated_at
email email, email_verified — needs review
phone phone_number, phone_number_verified — needs review
offline_access Returns a refresh_token

Open platform apps get openid profile offline_access by default. Ask only for what you need. Users see the requested scopes on the consent screen.

The raw flow

If you're not using a library, this is what happens on the wire.

http
GET https://auth.htp.example/oauth2/authorize
    ?response_type=code
    &client_id=<client_id>
    &redirect_uri=https%3A%2F%2Fpartner.example.com%2Fauth%2Fuccard%2Fcallback
    &scope=openid%20profile%20offline_access
    &state=<state>
    &nonce=<nonce>
    &code_challenge=<code_challenge>
    &code_challenge_method=S256

On the callback, check state and iss, then exchange the code (valid once, for 5 minutes):

bash
curl -X POST https://auth.htp.example/oauth2/token \
  -u "<client_id>:<client_secret>" \
  -d grant_type=authorization_code \
  -d code=<code> \
  -d redirect_uri=https://partner.example.com/auth/uccard/callback \
  -d code_verifier=<code_verifier>

Validate the id_token (signature from JWKS, iss, aud = your client_id, exp, nonce), then read sub.

Linking existing accounts

If you already have users with your own logins, let signed-in users connect UC Card from their account settings. Store the sub on the existing user record, and match on sub the next time they use the button.

Don't auto-merge accounts by email

Never link a UC Card login to an existing account only because the email matches. Ask the user to sign in to their existing account first, then connect UC Card.

The sub is pairwise

  • All apps of one developer receive the same sub for a user, so you can share users across your apps.
  • Different developers get different subs for the same person — users cannot be correlated across developers.
  • The sub never changes. Store it with your user record. If you also take payments, pass it as payer_sub / payee_sub.

Users can revoke access

In the UC Card App, users can remove your app under Authorized apps. After that, refresh tokens and userinfo stop working and you can no longer charge or pay that user (USER_NOT_AUTHORIZED) until they sign in again.

Sandbox apps

Before your app is published, only you and its test users can sign in; anyone else gets access_denied. The login screen marks unreviewed apps to users.