agentsclimarketplace

Mobile auth backend

Skill almasumdev/awesome-mobile-backend-agent-skills/.github/skills/auth/mobile-auth-backend

Agent skills for the backend-for-mobile layer: APIs, auth, push, sync, and BaaS integrations.

Install
npx -y skills add almasumdev/awesome-mobile-backend-agent-skills --skill mobile-auth-backend

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Server-side OAuth 2.1 + PKCE for native mobile apps -- authorization endpoint, token endpoint, refresh rotation, and device binding. Use when implementing or reviewing the auth server for mobile clients.

SKILL.md

5.5 KB, as published. Nobody here has run it

Mobile Auth Backend (OAuth 2.1 + PKCE)

Instructions

Native mobile apps cannot hold a confidential client secret. The only defensible interactive-login flow is OAuth 2.1 Authorization Code with PKCE, using the system browser (ASWebAuthenticationSession on iOS, Custom Tabs on Android). No embedded WebView. No resource-owner password grant.

1. Flow Overview

App generates code_verifier (random 43-128 bytes) and code_challenge = BASE64URL(SHA256(code_verifier))

App -> /authorize?response_type=code
                  &client_id=mobile
                  &redirect_uri=com.example.app:/oauth/callback
                  &code_challenge=<b64url>
                  &code_challenge_method=S256
                  &state=<random>
                  &scope=openid profile offline_access

User signs in in system browser -> redirect back with ?code=... &state=...

App -> POST /token (code, code_verifier, redirect_uri, client_id)
                  -> { access_token, refresh_token, expires_in, id_token? }

2. Authorization Endpoint

Register each mobile client with:

  • client_id (public, no secret).
  • Allowed redirect URIs: universal links (https://app.example.com/oauth/callback) are preferred over custom schemes where possible. Custom schemes (com.example.app:/oauth/callback) are allowed.
  • Allowed scopes and response types (code only).
  • PKCE required; reject code_challenge_method=plain.

Validate redirect_uri with exact string match. Never prefix-match.

3. Token Endpoint

// Node/TS (Express-ish pseudocode)
app.post("/oauth/token", async (req, res) => {
  const { grant_type, code, code_verifier, redirect_uri, client_id, refresh_token } = req.body;
  if (grant_type === "authorization_code") {
    const entry = await codeStore.consume(code); // single use
    if (!entry || entry.clientId !== client_id || entry.redirectUri !== redirect_uri) {
      return res.status(400).json({ error: "invalid_grant" });
    }
    const challenge = base64url(sha256(code_verifier));
    if (challenge !== entry.codeChallenge) {
      return res.status(400).json({ error: "invalid_grant" });
    }
    return res.json(await issueTokens(entry.userId, client_id, entry.deviceId));
  }
  if (grant_type === "refresh_token") {
    return res.json(await rotateRefresh(refresh_token, client_id));
  }
  return res.status(400).json({ error: "unsupported_grant_type" });
});

Access tokens are short-lived (5–15 minutes). Refresh tokens are long-lived but rotated on every use (see next section).

4. Refresh Rotation and Replay Detection

Every refresh request returns a new refresh token and invalidates the previous one. Store refresh tokens hashed (bcrypt/argon2 is overkill here; HMAC-SHA256 with a server-side pepper is standard) and track a session family id.

session_family_id   -> (user_id, device_id, created_at)
refresh_token_hash  -> (session_family_id, issued_at, rotated_at?, revoked?)

On refresh:

  1. Look up the token by hash.
  2. If already rotated or revoked -> treat as replay attack: revoke the entire session_family_id and return invalid_grant. Alert.
  3. Otherwise, mark the old token rotated, issue a new pair bound to the same family.

This is RFC 6749 / OAuth 2.1 "refresh token rotation with reuse detection".

5. Device Binding

Each login creates a device_id (stable random on first launch, stored in Keychain / EncryptedSharedPreferences). Bind the session family to that device. Where the platform supports it, strengthen with:

  • iOS: DeviceCheck / App Attest assertion embedded in the token request.
  • Android: Play Integrity API verdict.

Reject token exchanges whose attestation does not match the registered device.

6. Access Tokens

Prefer short-lived JWTs signed with RS256 / EdDSA so resource services can verify without calling the auth server. Claims:

{
  "iss": "https://auth.example.com",
  "sub": "user_01HX7...",
  "aud": "api",
  "exp": 1713523200,
  "iat": 1713522600,
  "scope": "profile feed",
  "device_id": "dev_01HX7...",
  "sid": "sess_01HX7..."
}

Publish JWKS at /.well-known/jwks.json and rotate keys every 90 days with overlap.

7. Logout and Revocation

  • POST /oauth/revoke with a refresh token: revoke the session family.
  • POST /oauth/logout invalidates the current session family and returns 204.
  • Access tokens are not individually revocable; short expiry is the mitigation. For sensitive actions (password change, device remove), publish to a revocation list (short-lived Redis set) that resource servers check.

8. Rate Limiting and Abuse

  • Rate-limit /token per client_id + IP and per device_id.
  • Lockout /authorize credential checks per account and per IP with exponential backoff.
  • Log all failed refresh rotations; repeated failures trigger session-family revocation.

Checklist

  • PKCE with S256 required; plain rejected.
  • Redirect URIs exact-matched; universal links preferred.
  • Access tokens short-lived (≤ 15 min), JWT signed with asymmetric key.
  • Refresh tokens rotated on every use with replay detection and family revocation.
  • Sessions bound to device_id; attestation verified where available.
  • /revoke and /logout implemented; short-lived denylist for urgent revokes.
  • JWKS endpoint with 90-day key rotation.
  • Rate limits on /token and /authorize with abuse alerting.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.