Sign in with Rankly
Permetti agli utenti Rankly di accedere alla tua app con il loro account Rankly. Implementa OAuth 2.0 + OpenID Connect standard contro gli endpoint pubblicati su Rankly. Niente librerie custom: qualsiasi client OIDC funziona out-of-the-box.
1. Cos'è e quando usarlo
Sign in with Rankly è un OAuth 2.0 + OpenID Connect provider gestito da Rankly. Usalo quando:
- Vuoi permettere agli utenti Rankly di loggarsi nella tua app senza creare un secondo account.
- Vuoi leggere/scrivere dati Rankly a nome di un utente specifico (rispettando i suoi permessi sulle org di cui è membro).
- Stai costruendo un bot Discord, un overlay caster, un'app mobile, una dashboard custom che deve agire come quell'utente.
Per integrazioni server-to-server senzaun utente specifico (es. job notturno che legge tutti i tornei di un'org), usa invece le API key Bearer: sono org-bound, più semplici, e non richiedono il flow utente.
2. Registrare la tua app
Self-service: se sei admin/owner di un'organizzazione Rankly, registri il client da Account → Organizzazione → App OAuth in pochi secondi. Ottieni client_id (pubblico) + client_secret (segreto, mostrato una sola volta).
Devi indicare:
- Nome app (quello che l'utente vede sulla pagina di consenso).
- Tipo:
web(backend server-side con client_secret),public(SPA/native con PKCE solo),native,user-agent-based. - Redirect URI(s): l'URL della tua app dove Rankly rispedirà l'utente dopo il consenso.
https://obbligatorio (eccettohttp://localhostper dev).
Conserva il client_secret nel password manager / vault del tuo deploy. Il secret non è recuperabile: se lo perdi, cancella il client e creane uno nuovo.
3. Discovery URL
Tutto parte da qui. Il discovery URL espone gli endpoint, gli algoritmi supportati e la JWKS URI in formato JSON standard OIDC:
GET https://api.rankly.it/api/auth/.well-known/openid-configurationQualsiasi libreria OIDC moderna (openid-client per Node.js, Authlib per Python, AppAuth per mobile) lo legge in automatico. Non serve hardcodare gli URL dei singoli endpoint.
4. Authorization Code Flow
È il flow standard server-side. Per SPA/native usa la variante con PKCE (S256 supportato).
Step 1 — redirect a Rankly
La tua app costruisce l'URL di authorize e ci spedisce l'utente:
https://api.rankly.it/api/auth/oauth2/authorize?
response_type=code
&client_id=<YOUR_CLIENT_ID>
&redirect_uri=<YOUR_REDIRECT_URI>
&scope=openid profile email tournaments:read
&state=<RANDOM_STRING_FOR_CSRF>
&code_challenge=<PKCE_S256_CHALLENGE> # se PKCE
&code_challenge_method=S256 # se PKCERankly verifica la session utente: se non è loggato, lo manda a /signin. Una volta loggato, mostra la pagina di consenso con i tuoi scope tradotti in italiano. L'utente preme Autorizza → Rankly redirige al tuo redirect_uri con:
<YOUR_REDIRECT_URI>?code=<AUTH_CODE>&state=<TUO_STATE>Importante: verifica che state coincida con quello che hai mandato (CSRF guard).
Step 2 — scambio code → token
Lato server (mai dal browser per i client web):
POST https://api.rankly.it/api/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=authorization_code
&code=<AUTH_CODE>
&redirect_uri=<YOUR_REDIRECT_URI>
&code_verifier=<PKCE_VERIFIER> # se PKCERisposta:
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "...",
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"scope": "openid profile email tournaments:read"
}Esempio Node.js (openid-client)
import { Issuer } from 'openid-client';
const issuer = await Issuer.discover('https://api.rankly.it/api/auth');
const client = new issuer.Client({
client_id: process.env.RANKLY_CLIENT_ID,
client_secret: process.env.RANKLY_CLIENT_SECRET,
redirect_uris: ['https://your-app.com/auth/callback'],
response_types: ['code'],
});
// Step 1: redirect
const url = client.authorizationUrl({
scope: 'openid profile email tournaments:read',
state,
});
// Step 2 (route /auth/callback):
const params = client.callbackParams(req);
const tokenSet = await client.callback(redirectUri, params, { state });
const userinfo = await client.userinfo(tokenSet.access_token);
// userinfo => { sub, name, email, ... }Esempio cURL
# Step 2 dopo aver ricevuto ?code=XYZ
curl -X POST https://api.rankly.it/api/auth/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=authorization_code" \
-d "code=XYZ" \
-d "redirect_uri=https://your-app.com/auth/callback"5. Scope disponibili
openid— obbligatorio per OIDC, identifica l'utente (subclaim).profile— accesso a username, nome.email— accesso all'email.offline_access— emetterefresh_token, permette di rinnovare l'access_token senza re-login.tournaments:read— chiamate GET su/api/v1/orgs/{orgId}/tournamentse affini, nei limiti delle membership dell'utente.tournaments:write— chiamate POST/PATCH/DELETE su tornei, match, participants. Richiede membershipadmin/ownerdell'org target.
Chiedi solo gli scope che usi davvero. Più scope chiedi, più la pagina di consenso risulta intrusiva, meno utenti accettano.
6. Profilo utente
GET https://api.rankly.it/api/auth/oauth2/userinfo
Authorization: Bearer <access_token>Risposta:
{
"sub": "usr_xxx",
"name": "Andrea Gasloli",
"preferred_username": "gas",
"email": "andrea@example.com",
"email_verified": true
}7. Chiamate API a nome utente
L'access_tokenemesso vale anche come Bearer per l'API REST di Rankly https://api.rankly.it/api/v1/*:
curl https://api.rankly.it/api/v1/orgs/<orgId>/tournaments \
-H "Authorization: Bearer <access_token>"Regole:
- Membership check: il backend verifica che l'utente sia member dell'org target. Se non lo è →
403 oauth_user_not_member. - Scope check: le mutation richiedono
tournaments:write. Le read richiedonotournaments:readimplicito o esplicito. - Ereditarietà admin: se l'utente è admin/owner di una federazione, può accedere a tutti i club affiliati (sub-org) senza membership esplicita su ciascuno.
- Subscription: l'org target deve avere sub
trialingoactive. Altrimenti read sono ok, write →402 subscription_required.
8. Refresh token
Se hai chiesto lo scope offline_access, ricevi un refresh_tokeninsieme all'access_token. Usalo per rinnovare:
POST https://api.rankly.it/api/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=refresh_token
&refresh_token=<REFRESH_TOKEN>Durata di default: access_token 1 ora, refresh_token 7 giorni. Rotation: ogni refresh emette un nuovo refresh, il precedente viene invalidato (rotazione standard OIDC).
9. Verifica id_token (JWKS)
Gli id_token sono JWT firmati RS256. Verifica la firma offline scaricando la chiave pubblica da:
GET https://api.rankly.it/api/auth/jwksLe librerie OIDC fanno questa verifica in automatico (jose, jsonwebtoken con jwks-rsa, ecc). La rotazione delle chiavi è gestita lato Rankly: il kidnell'header del JWT indica quale chiave usare.
# Esempio con jose (Node.js)
import { createRemoteJWKSet, jwtVerify } from 'jose';
const JWKS = createRemoteJWKSet(
new URL('https://api.rankly.it/api/auth/jwks'),
);
const { payload } = await jwtVerify(idToken, JWKS, {
issuer: 'https://api.rankly.it',
audience: process.env.RANKLY_CLIENT_ID,
});10. Errori comuni
Sul flow OAuth
invalid_client: client_id non trovato o client_secret sbagliato. Verifica le credenziali.invalid_grant: code già scambiato (single-use), scaduto (10 min), o redirect_uri diverso da quello del request.unauthorized_client: il tuo client non è autorizzato a usare quel grant_type. Perwebok auth_code+refresh, perpublicsolo auth_code+PKCE.- Redirect dopo consenso fallisce: probabile
redirect_urinon whitelisted in fase di registrazione.
Sull'API call
401 invalid_token: access_token scaduto o revocato dall'utente. Usa il refresh_token.401 token_expired: come sopra.403 oauth_user_not_member: l'utente non è member dell'org target.403 scope_required:tournaments:write: mancano scope per la mutation. Richieditournaments:writenello scope iniziale.402 subscription_required: l'org target non ha subscription attiva.
Contatto + revoca lato utente
Email tecnico: support@rankly.it. Risposta in italiano entro 1 giorno lavorativo.
Lato utente: gli utenti Rankly vedono le tue app autorizzate su /account/oauth-authorizationse possono revocarle in qualsiasi momento. Dopo la revoca, l'utente dovrà riautorizzare la tua app dal flusso /authorize standard.