Overview
Visit Korat is an OpenID Connect provider. Add one button and people sign in to your app with the Visit Korat account they already have. You receive a verified email address and a display name; you never handle a password.
Nothing here is bespoke. OAuth 2.0 authorization code flow (RFC 6749), mandatory PKCE S256 (RFC 7636), OpenID Connect Core and Discovery 1.0, token revocation (RFC 7009). Any conformant client library works — the same one you would point at Google or Apple.
How it works
sequenceDiagram
autonumber
participant U as Person
participant A as Your app
participant V as Visit Korat
U->>A: Clicks "Sign in with Visit Korat"
A->>U: Redirect to /oauth/authorize
U->>V: Signs in with a magic link
V->>U: Shows exactly what you asked for
U->>V: Agrees
V->>A: Redirect back with code + state
A->>V: POST /oauth/token (server to server)
V->>A: access_token + id_token
A->>U: Signed inThe authorization code in step 6 lives 60 seconds and can be used once, and is worthless without the PKCE verifier that never left your server. That is why it is safe for it to travel in a URL, where browser history and proxy logs can see it.
Step 7 is server to server. A confidential client that calls the token endpoint from a browser is refused — see storing your client secret.
Request access
Access is requested, then granted by a person at Visit Korat. You can register an application yourself in a couple of minutes, but it issues no tokens until somebody here has looked at it.
flowchart TD
R["You register an app<br/>at /developers/apps"] --> P["pending<br/>no tokens issued yet"]
P --> H{"Visit Korat staff<br/>review the request"}
H -->|Approved| OK["approved<br/>tokens are issued"]
H -->|Needs changes| P
OK --> W["You widen redirect URIs,<br/>origins or scopes"]
W --> P
OK --> S["suspended<br/>tokens stop immediately"]
classDef clay fill:#F7EFE8,stroke:#A86B3D,color:#292723;
classDef sage fill:#EEF3ED,stroke:#7FA378,color:#292723;
classDef lagoon fill:#EAF1F5,stroke:#3B7FA1,color:#292723;
class H lagoon
class OK sage
class S clay- Sign in at your applications with your own Visit Korat account — the same one you use for the rest of the site, no separate signup.
- Describe what you are building, and list the exact redirect URIs and scopes you need.
- You receive a
client_idimmediately, and aclient_secretonce if you registered a confidential client. - The application sits at pending. Requests to
/oauth/authorizeare refused while it does. - A reviewer here checks the redirect URIs really belong to you, that the scopes match what the app does, and that your privacy policy opens. Then they approve it.
Why the wait.A redirect URI is where a real person’s email address gets delivered. Approving one is a statement that the destination is ours to vouch for, and that is not a judgement a form can make. Widening an approved application later — a new redirect URI, a new scope — sends it back for the same review, for the same reason.
Need offline_access (refresh tokens)? Ask for it in your description. It is a separate decision from approval, because a refresh token keeps working for thirty days with nobody watching.
Quick start
Start from the discovery document rather than hardcoding URLs. It is one fetch, and it is what lets an endpoint move without breaking your integration.
curl -s https://visitkorat.com/.well-known/openid-configuration | jqWith a library that supports OIDC discovery — which is nearly all of them — three values are the whole configuration:
const ISSUER = "https://visitkorat.com";
const CLIENT_ID = "your-app-3f2a91c4";
const REDIRECT = "https://example.com/auth/callback";Then follow the integration guides, which have runnable code for a web app with a backend, an SPA, and a mobile app.
Environments
| Environment | Issuer | Who can register |
|---|---|---|
| Development | https://dev.visitkorat.com | Anyone with a Visit Korat account |
| Production | https://visitkorat.com | Visit Korat staff, on request |
The two are entirely separate registries — separate clients, separate secrets, separate consent records. A code issued by one cannot be redeemed at the other, and that is deliberate.
Build and test against development. When you are ready for production, contact the Visit Korat team with your client_id.
You are reading the prod documentation, and every example on these pages points at https://visitkorat.com.
The authorization code flow, PKCE, scopes, and what each token is for.
Every endpoint, with real requests and responses — generated from openapi.yaml.
Working code for server-rendered web apps, SPAs, mobile apps, and client libraries.
What you have to get right, and why we are strict about each of them.
Every error code, and what actually causes it in practice.