Help/ Integration
Web

Login with TTAR

Authorization with a TTAR account on your website or app: players sign in with one click, and you see their rating right away.

If you run a website or an app for table tennis players — a club, tournaments, coaching, an equipment shop — add “Login with TTAR”. Players will be able to sign in to your service with their TTAR account in one click, just like with Google or Telegram, without a new username and password. And you immediately learn who has come to you and how strong a player they are.

What it gives your service:

  • More sign-ups. No forms to fill in and no email to confirm: players log in with their TTAR login, so fewer people abandon the registration halfway.
  • The player's rating right away. Together with the authorization you receive the TTAR rating: use it to seed a tournament, split participants into groups by strength, find a sparring partner or check eligibility for a competition.
  • No authorization of your own to build. Password storage, account recovery, sign-in with Google and Telegram — TTAR already does all of that. Your developers only need to connect the standard OpenID Connect protocol, with ready-made libraries for every popular programming language.
  • Safe for players. You never receive the TTAR password: players enter it only on the TTAR page. You get only the data you asked for — the player ID, name and avatar, email and rating.
How to connect
Becoming a partner is simple and free: write to us at kot@ttar.app and tell us about your service — we will send you everything you need to connect. Your players will not see an “Allow access?” screen: we connect partners ourselves, so they are pre-approved.

Below is the technical description. You can pass this page straight to your developers.

Authorization server endpoints

Most OIDC libraries only need the Issuer: they read the other addresses from the discovery document.

Issuer          https://stage.api.ttar.app
Discovery       https://stage.api.ttar.app/.well-known/openid-configuration
Authorization   https://stage.api.ttar.app/connect/authorize
Token           https://stage.api.ttar.app/connect/token
UserInfo        https://stage.api.ttar.app/connect/userinfo
End session     https://stage.api.ttar.app/connect/logout
JWKS            https://stage.api.ttar.app/.well-known/jwks

Client registration

Each partner receives a client_id. There is no client secret — only PKCE (code_challenge_method=S256) is supported. To register, write to us at kot@ttar.app.

During registration you provide one or more redirect_uri values — the URLs in your application where we will redirect the user after authorization. We add them to a whitelist. In each request you specify the exact URI you want to use, and the server validates it against that list.

Optionally you also provide one or more post_logout_redirect_uri values — where we send the user back after a logout through our end-session endpoint /connect/logout (see “Logout” below). This is a separate whitelist: a redirect_uri is not accepted as a post-logout target. You only need it if you use that logout.

Sign-in: Authorization Code + PKCE

Step 1. Redirect the user to the authorization endpoint. Build the URL below and navigate the user's browser to it as a full page navigation, not an iframe:

GET https://stage.api.ttar.app/connect/authorize
  ?client_id=YOUR_CLIENT_ID
  &response_type=code
  &redirect_uri=https://yourapp.com/callback
  &scope=openid profile email ttar:rating
  &code_challenge=BASE64URL(SHA256(code_verifier))
  &code_challenge_method=S256
  &state=RANDOM_OPAQUE_VALUE

If the user is not signed in to TTAR in this browser yet, they see the TTAR login page and sign in. If they already have an active TTAR session, the login page is skipped and the code is issued right away (single sign-on) — unless you ask for a fresh login with prompt=login. The optional prompt and max_age parameters are described in “Re-authentication and account switching” below.

Step 2. Receive the response at your redirect_uri. After a successful login the browser is automatically redirected to your redirect_uri with two query parameters:

GET https://yourapp.com/callback?code=AUTHORIZATION_CODE&state=RANDOM_OPAQUE_VALUE
  • code — a one-time authorization code. It is valid for about 60 seconds, so exchange it immediately.
  • state — the same value you sent in step 1. Always verify it matches what you stored on your side: this protects against CSRF.

If the user denied access or an error occurred, you get:

GET https://yourapp.com/callback?error=access_denied&error_description=...&state=...

Step 3. Exchange the code for tokens. From your server, not the browser, send a POST with the code from step 2:

POST https://stage.api.ttar.app/connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=YOUR_CLIENT_ID
&code=AUTHORIZATION_CODE
&redirect_uri=https://yourapp.com/callback
&code_verifier=YOUR_CODE_VERIFIER
Important
redirect_uri here must match exactly what was sent in step 1: the server uses it as an additional binding check.

Response:

{
  "access_token": "...",
  "id_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600
}
  • access_token — a Bearer token for API calls, including /connect/userinfo. It is a JWT signed with RS256.
  • id_token — a JWT with basic user identity: sub, name, email, etc. Verify its signature before trusting it.
  • refresh_token — to obtain new tokens without asking the user to log in again. Issued only when you requested the offline_access scope.

Step 4. Refresh tokens. When the access token expires, get new tokens with the refresh token:

POST https://stage.api.ttar.app/connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=YOUR_CLIENT_ID
&refresh_token=REFRESH_TOKEN

Scopes

ScopeReturns
openidsub (the TTAR player ID). Required.
profilename, picture (avatar URL)
emailemail, email_verified
offline_accessAdds a refresh_token to the response of the token endpoint /connect/token. Without this scope no refresh token is issued.
ttar:ratingThe ttar_rating claim in the access token — an array of the player's ratings (see below).

The ttar_rating claim

When ttar:rating is requested and the player has a rating, the access token contains a ttar_rating claim. It is a JSON array with one entry per hand — the main and the weak one:

[
  {
    "handType": "Main",
    "rating": 1456,
    "games": 120,
    "qualificationPoints": 85,
    "isRated": true
  },
  {
    "handType": "Weak",
    "rating": 1102,
    "games": 15,
    "qualificationPoints": 10,
    "isRated": false
  }
]

Additional user fields (name, avatar, email) are available from the UserInfo endpoint /connect/userinfo or inside the id_token.

Re-authentication and account switching

TTAR keeps a single sign-on (SSO) session in the user's browser — a cookie on the TTAR API domain. While it is active, /connect/authorize returns a code for the same TTAR user without showing the login page. This session is independent of your application's session: logging the user out of your app does not end it.

  • prompt=login — always shows the TTAR login page and makes the user sign in again, even with an active session: an existing TTAR session is never reused. The user may sign in with a different TTAR account. Recommended for account linking.
  • prompt=select_account — same as prompt=login. TTAR has no account picker: the user chooses the account by signing in with it.
  • prompt=none — never shows any UI. Without an active session, or with one older than max_age, the user is sent back to your redirect_uri with error=login_required.
  • prompt=consent — accepted, has no effect: registered partners are pre-approved, TTAR shows no consent screen.
  • max_age=N — if the user signed in more than N seconds ago, they must sign in again. max_age=0 is the same as prompt=login.

An invalid prompt (an unknown value, or none combined with another value) is rejected with HTTP 400 on the TTAR side — the browser is not redirected back to your redirect_uri.

The auth_time claim. The id_token contains auth_time — the Unix time in seconds of the user's last interactive sign-in to TTAR: email and password, Google or Telegram. It stays unchanged when tokens are refreshed. It may be missing only for TTAR sessions started before this feature was released. Such a session never satisfies prompt=login or max_age and is always re-established, so when you send either parameter the id_token always contains auth_time.

Linking a TTAR account:

  1. Add prompt=login to the authorization request and remember when you started it.
  2. After exchanging the code, verify that auth_time is not earlier than that moment, allowing a few seconds of clock skew. This confirms the user actually signed in during this request rather than an existing session being reused.
  3. Link on sub — the TTAR player ID.
Note
With Google sign-in, Google itself may skip asking for the password if the user is already signed in to Google in this browser. For TTAR this is still a fresh interactive sign-in, and auth_time reflects it.

You do not need a logout to let the user link a different TTAR account — prompt=login is enough.

Logout

Logging the user out of your application does not end their TTAR session. If you also want to end it in this browser (for example “sign out everywhere” or a shared computer), send the user's browser to the end-session endpoint /connect/logout as a full-page navigation. An XHR or an iframe will not work: the session cookie belongs to the TTAR domain.

GET https://stage.api.ttar.app/connect/logout
  ?client_id=YOUR_CLIENT_ID
  &post_logout_redirect_uri=https://yourapp.com/logged-out
  &state=RANDOM_OPAQUE_VALUE
  &id_token_hint=ID_TOKEN
  • TTAR deletes its session cookie and redirects the browser to post_logout_redirect_uri with state appended.
  • post_logout_redirect_uri must be registered in advance. The match is exact, and it is a separate list from redirect_uri (see “Client registration”). An unregistered value makes TTAR reject the whole request with HTTP 400 — and the session is not ended.
  • Without post_logout_redirect_uri the session is ended, but the user is not returned to your application.
  • id_token_hint is optional. If you send it, it must be an id_token issued to your client_id. An expired one is fine.
  • This ends the user's TTAR session in this browser for every service that has “Login with TTAR”, not only yours.

Token validation

Tokens are signed with RS256. Public keys are available at the standard JWKS URL:

https://stage.api.ttar.app/.well-known/jwks

Any standard OIDC library will pick them up automatically via the discovery endpoint. Verify:

  • the signature: alg=RS256, key from JWKS;
  • iss = https://stage.api.ttar.app;
  • aud = your client_id;
  • exp: the token has not expired;
  • auth_time, when you use prompt=login or max_age (see “The auth_time claim” above).

Staging notes

  • Staging is a test environment for your experiments.
  • A test account will be provided separately.
  • When moving to production, your client_id stays the same — only the Issuer changes, to https://api.ttar.app.
The page stopped responding. Reload 🗙