Blog | G5 Cyber Security

Offline App Authorization

TL;DR

This guide shows how to securely authorize users in an offline application without constant internet connection. We’ll use a token-based system, storing tokens locally and refreshing them when possible.

1. Choose an Authentication Method

Before dealing with offline access, you need a way for users to initially log in. Common options include:

For this guide, we’ll assume you have a working authentication system that returns a JSON Web Token (JWT) upon successful login.

2. Understanding JWTs

JWTs are self-contained tokens containing user information and an expiration time. They’re digitally signed to ensure integrity. A typical JWT looks like this:

Header.Payload.Signature

The Header describes the token type and signing algorithm.

The Payload contains claims about the user (e.g., user ID, roles).

The Signature verifies the token hasn’t been tampered with.

3. Initial Login & Token Storage

  1. When a user logs in successfully, your server should return a JWT.
  2. Store this JWT securely on the client-side. Do not store it in LocalStorage due to XSS vulnerabilities. Use:
    • HttpOnly Cookies: Best for web applications; inaccessible via JavaScript.
    • Secure Storage APIs: Available in native mobile apps (e.g., Keychain on iOS, KeyStore on Android).
  3. Set an expiration time for the token.

4. Offline Authorization Checks

  1. Before allowing access to protected resources, check if a valid JWT exists in storage.
  2. If a token is found:
    • Verify the Signature: Use a library appropriate for your programming language (e.g., jsonwebtoken in Node.js) to verify the token’s signature against your server’s public key.
    • Check Expiration Time: Ensure the token hasn’t expired.
    • If both checks pass, grant access.
  3. If no valid token is found, redirect the user to the login page.

Example (Node.js with jsonwebtoken):

const jwt = require('jsonwebtoken');
const publicKey = 'YOUR_PUBLIC_KEY'; // Replace with your server's public key

token = localStorage.getItem('token');

jwt.verify(token, publicKey, (err, decoded) => {
  if (err) {
    // Token is invalid or expired
    console.error(err);
    // Redirect to login page
  } else {
    // Token is valid
    console.log('User ID:', decoded.userId);
    // Grant access
  }
});

5. Token Refreshing

Tokens expire for security reasons. Implement a mechanism to refresh them without requiring the user to re-enter their credentials.

  1. Refresh Tokens: When the user logs in, also issue a long-lived refresh token alongside the JWT. Store this refresh token securely (similar to the JWT).
  2. Background Refresh: Periodically (e.g., every hour), attempt to use the refresh token to request a new JWT from your server. Do this in the background, without interrupting the user experience.
  3. Server-Side Validation: The server should validate the refresh token before issuing a new JWT. Consider limiting the number of times a refresh token can be used (to prevent abuse).

Example Refresh Token Flow:

6. Security Considerations

Exit mobile version