Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JonathanHerSa/xolo-api-hub/llms.txt

Use this file to discover all available pages before exploring further.

OAuth 2.0 is the industry-standard protocol for delegated API authorization. Xolo implements three grant types natively — Authorization Code with PKCE, Client Credentials, and Password Grant — directly inside the mobile client, without relying on any external proxy or desktop helper. Token acquisition, PKCE challenge generation, and automatic token refresh are all handled on-device by OAuth2Service.

Grant Types

The Authorization Code flow is the most secure grant type for interactive, user-facing authentication. Xolo uses the PKCE (Proof Key for Code Exchange) extension — mandatory for public clients — to prevent authorization-code interception attacks.How it works in Xolo: OAuth2Service.authorizeAndGetToken() spins up an ephemeral local HTTP server on a random port in the range 49152–59151. It then constructs the authorization URL with a code_challenge derived from a freshly generated codeVerifier (SHA-256, base64url-encoded), and opens it in the device’s default browser via url_launcher. Once the user authenticates with the identity provider, the browser is redirected to http://localhost:<port> and the server captures the authorization code. Xolo validates the state parameter to prevent CSRF, then exchanges the code for tokens using getAccessToken() with grant_type=authorization_code.Required fields:
FieldDescription
authUrlAuthorization endpoint URL (e.g. https://auth.example.com/authorize)
tokenUrlToken endpoint URL (e.g. https://auth.example.com/token)
clientIdThe OAuth client identifier registered with the provider
clientSecretThe client secret (optional for public clients)
scopeSpace-separated list of requested scopes
The redirectUri and PKCE parameters (codeVerifier, codeChallenge) are generated and managed automatically by Xolo — you do not enter them manually.
The Client Credentials grant is designed for machine-to-machine (M2M) communication where no user interaction is needed. It authenticates the application itself rather than a specific user.Xolo POSTs directly to the token endpoint with grant_type=client_credentials. No browser is opened and no user interaction is required.Required fields:
FieldDescription
tokenUrlToken endpoint URL
clientIdThe OAuth client identifier
clientSecretThe client secret
scope(Optional) Space-separated list of requested scopes
final token = await oauth2Service.getAccessToken(
  tokenUrl: 'https://auth.example.com/token',
  clientId: 'my-service-client',
  clientSecret: 'client-secret-value',
  grantType: 'client_credentials',
  scope: 'read:metrics write:events',
);
The Password Grant (Resource Owner Password Credentials) passes a user’s username and password directly to the token endpoint. It is suitable for trusted first-party clients where the Authorization Code flow is impractical.Xolo sends grant_type=password along with the user credentials and client credentials in a single application/x-www-form-urlencoded POST.Required fields:
FieldDescription
tokenUrlToken endpoint URL
clientIdThe OAuth client identifier
clientSecretThe client secret
usernameThe resource owner’s username
passwordThe resource owner’s password
scope(Optional) Space-separated list of requested scopes
final token = await oauth2Service.getAccessToken(
  tokenUrl: 'https://auth.example.com/token',
  clientId: 'my-app',
  clientSecret: 'client-secret-value',
  grantType: 'password',
  username: 'alice@example.com',
  password: 'hunter2',
  scope: 'openid profile',
);

Token Refresh

When a stored OAuth 2.0 access token approaches expiry, OAuth2Service.maybeRefreshOAuth2AuthData() checks whether a refresh is needed and performs it automatically. Refresh is triggered when the token’s expiresAt timestamp is within 60 seconds of the current time. To refresh a token manually, call refreshAccessToken() directly:
final refreshed = await oauth2Service.refreshAccessToken(
  tokenUrl: 'https://auth.example.com/token',
  clientId: 'my-app',
  clientSecret: 'client-secret-value',
  refreshToken: 'stored-refresh-token',
);

// refreshed contains:
// {
//   "access_token": "new-access-token",
//   "refresh_token": "rotated-refresh-token",  // if the server rotates tokens
//   "expires_in": 3600
// }
The method POSTs grant_type=refresh_token along with the client credentials to the token endpoint. If the response includes a new refresh_token, Xolo replaces the stored one. If expires_in is present, a new expiresAt timestamp is computed and persisted. The updated auth data is stored back through AuthSecretService, keeping all credentials in flutter_secure_storage. Automatic refresh applies only to the authorization_code grant type (i.e. tokens that originally came from an interactive browser flow).

OAuth2Service.getAccessToken() Reference

Future<String> getAccessToken({
  required String tokenUrl,
  required String clientId,
  required String clientSecret,
  String? grantType,       // defaults to 'client_credentials'
  String? username,        // required for 'password' grant
  String? password,        // required for 'password' grant
  String? scope,           // optional; space-separated scopes
  String? code,            // required for 'authorization_code' grant
  String? redirectUri,     // required for 'authorization_code' grant
  String? codeVerifier,    // required for 'authorization_code' + PKCE
})
The method sends an application/x-www-form-urlencoded POST to tokenUrl. On a 200 response it returns the raw access_token string. Any non-200 status code or network error throws an Exception. Parameters:
tokenUrl
string
required
The full URL of the OAuth 2.0 token endpoint.
clientId
string
required
The client identifier issued by the authorization server.
clientSecret
string
required
The client secret issued by the authorization server. Pass an empty string for public clients.
grantType
string
One of client_credentials, password, or authorization_code. Defaults to client_credentials when omitted.
username
string
Resource owner username. Only included in the request body when grantType is password.
password
string
Resource owner password. Only included in the request body when grantType is password.
scope
string
Space-separated list of requested scopes. Omitted from the request body when empty or null.
code
string
The authorization code received from the redirect. Only included when grantType is authorization_code.
redirectUri
string
The redirect URI that was registered and used in the authorization request. Only included when grantType is authorization_code.
codeVerifier
string
The PKCE code verifier. Only included when grantType is authorization_code. Xolo generates this automatically when using authorizeAndGetToken().
Example — Client Credentials:
final oauth2Service = ref.read(oauth2ServiceProvider);

final accessToken = await oauth2Service.getAccessToken(
  tokenUrl: 'https://auth.example.com/oauth/token',
  clientId: 'api-gateway-client',
  clientSecret: 'super-secret',
  grantType: 'client_credentials',
  scope: 'api:read api:write',
);

// accessToken is the raw JWT or opaque token string
print(accessToken);

PKCE Flow Step-by-Step

1

Generate PKCE Parameters

Xolo generates a cryptographically random codeVerifier (64 URL-safe characters) using Random.secure(). It then computes the codeChallenge by hashing the verifier with SHA-256 and encoding the result as base64url (with padding stripped):
String _pkceS256(String verifier) {
  final digest = sha256.convert(utf8.encode(verifier));
  return base64Url.encode(digest.bytes).replaceAll('=', '');
}
A random state value (32 characters) is also generated to protect against CSRF.
2

Start Local Redirect Server

Xolo binds an ephemeral HttpServer to 127.0.0.1 on a random port between 49152 and 59151. This server listens for the single incoming redirect from the identity provider.
3

Open Authorization URL in Browser

The authorization URL is constructed with response_type=code, code_challenge_method=S256, and the generated codeChallenge. Xolo opens this URL in the device’s default browser using url_launcher.
https://auth.example.com/authorize
  ?response_type=code
  &client_id=my-app
  &redirect_uri=http://localhost:52341
  &scope=openid profile
  &state=<random-state>
  &code_challenge=<sha256-base64url>
  &code_challenge_method=S256
4

User Authenticates

The user completes the login and consent flow in the browser. The identity provider redirects the browser to http://localhost:<port>?code=<auth-code>&state=<state>.
5

Capture Code and Exchange for Tokens

The local server captures the redirect request, validates the state parameter, and responds with a success page so the browser can be closed. Xolo then calls getAccessToken() with grant_type=authorization_code, passing the code, redirectUri, and codeVerifier. The identity provider verifies the PKCE challenge and returns the access token (and optionally a refresh token). The local server is closed immediately after.

Never share your clientSecret. Xolo stores all OAuth 2.0 credentials — including the client secret, access token, and refresh token — in flutter_secure_storage, not in the SQLite database. Credentials are stored as opaque references in SQLite and resolved from secure storage at request time. On Android this uses the Android Keystore; on iOS it uses the Keychain.

Build docs developers (and LLMs) love