Register your application with SW Combine
Before writing any code, register your OAuth application on the SW Combine developer portal at
https://www.swcombine.com/ws/developers/. You will receive a client ID and client secret, and you must register a redirect URI (callback URL) that SW Combine will redirect users to after authorization.For local development, register http://localhost:3000/callback as your redirect URI.Once you have your credentials, store them in environment variables — never hardcode them:.env
Initialize the client in full OAuth mode
Create a
SWCombine instance with your OAuth credentials. Pass AccessType.Offline if you want a refresh token so the SDK can automatically renew access without requiring the user to re-authorize:AccessType.Online (the default) returns only an access token. AccessType.Offline additionally returns a refresh token, enabling automatic renewal without user interaction.Generate an authorization URL and redirect the user
Call The
client.auth.getAuthorizationUrl() with the scopes your application needs and a randomly generated state value for CSRF protection. Redirect the user to the returned URL:state parameter is echoed back in the callback and lets you verify the response is genuine. Store it somewhere you can retrieve it at callback time — a session, cookie, or database row.Handle the OAuth callback
After the user authorizes (or denies) your app, SW Combine redirects them to your
redirectUri with a code and state query parameter. Your callback handler must verify the state and exchange the code for a token:handleCallback returns an AuthorizationResult object with a success boolean, and a token property when successful. The SDK also automatically sets the token on the client instance, so subsequent calls on the same client instance are immediately authenticated.Complete Express.js example
Here is a complete, working Express.js application that puts all steps together with session-based state management:Quick token helper for development
The SDK ships with a helper script that runs a local OAuth server and prints your access token to the terminal — no Express boilerplate required:http://localhost:3000/callback is registered as a redirect URI in your SW Combine OAuth application settings before running this script.
Security best practices
- Use HTTPS in production. Localhost HTTP is acceptable for development, but production redirect URIs must use HTTPS to protect the authorization code in transit.
- Validate the
stateparameter. Always compare the returnedstateto what you stored before callinghandleCallback. Never skip this check. - Store credentials in environment variables. Never commit
clientId,clientSecret, or tokens to source control. Add.envto your.gitignore. - Use
AccessType.Offlinewhen you need persistent access. This gives you a refresh token so the SDK can renew access automatically without requiring another user authorization. - Revoke refresh tokens on logout. Call
client.auth.revokeToken(refreshToken)when a user signs out to invalidate the token server-side.
Troubleshooting
Redirect URI mismatch
Redirect URI mismatch
The URI you pass as
redirectUri must exactly match the value registered in your SW Combine OAuth application — including the scheme (http vs https), port, and path. Common mismatches include a trailing slash, or using https locally when http is registered.Invalid scope format
Invalid scope format
Scope values are lowercase strings (e.g.,
character_read, messages_send). The API rejects uppercase values. Use the typed constants from the SDK to avoid this:Invalid state parameter
Invalid state parameter
If your callback returns an “invalid state” error, the state stored at login time doesn’t match the state returned in the callback. This often happens when the session is not persisting between the login and callback routes, or when the user follows an old authorization link. Send the user back through the login flow to generate a fresh state value.
Access token not provided
Access token not provided
Calls to authenticated endpoints fail if no token is set. Make sure you either pass
token to the constructor or call client.setToken() before making API requests.