### Install OAuth2 Client Package Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Use npm to install the @badgateway/oauth2-client package. ```sh npm i @badgateway/oauth2-client ``` -------------------------------- ### Initialize OAuth2Fetch Wrapper Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Sets up the OAuth2Fetch wrapper, which automatically adds Bearer tokens and refreshes them. Requires a client instance and a function to get a new token. ```typescript import { OAuth2Client, OAuth2Fetch } from '@badgateway/oauth2-client'; const client = new OAuth2Client({ server: 'https://my-auth-server', clientId: 'my-client-id' }); const fetchWrapper = new OAuth2Fetch({ client: client, /** * You are responsible for implementing this function. * it's purpose is to supply the 'initial' oauth2 token. */ getNewToken: async () => { // Example return client.clientCredentials(); // Another example return client.authorizationCode.getToken({ code: '..', redirectUri: '..', }); // You can return null to fail the process. You may want to do this // when a user needs to be redirected back to the authorization_code // endpoints. return null; }, /** * Optional. This will be called for any fatal authentication errors. */ onError: (err) => { // err is of type Error } }); ``` -------------------------------- ### Get Authorization URI Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Constructs the authorization URI for redirecting the user to the authorization server. Requires redirect URI, state, code verifier, and scopes. ```typescript // In a browser this might work as follows: document.location = await client.authorizationCode.getAuthorizeUri({ // URL in the app that the user should get redirected to after authenticating redirectUri: 'https://my-app.example/', // Optional string that can be sent along to the auth server. This value will // be sent along with the redirect back to the app verbatim. state: 'some-string', codeVerifier, scope: ['scope1', 'scope2'], }); ``` -------------------------------- ### Get Token from Redirect Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Exchanges the authorization code received from the redirect for an access token. Requires the redirect location, redirect URI, state, and code verifier. ```typescript const oauth2Token = await client.authorizationCode.getTokenFromCodeRedirect( document.location, { /** * The redirect URI is not actually used for any redirects, but MUST be the * same as what you passed earlier to "authorizationCode" */ redirectUri: 'https://my-app.example/', /** * This is optional, but if it's passed then it also MUST be the same as * what you passed in the first step. * * If set, it will verify that the server sent the exact same state back. */ state: 'some-string', codeVerifier, } ); ``` -------------------------------- ### Initialize OAuth2 Client Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Instantiate the OAuth2Client with server and client ID. Specify token and authorization endpoints if they cannot be auto-detected. ```typescript import { OAuth2Client, generateCodeVerifier } from '@badgateway/oauth2-client'; const client = new OAuth2Client({ server: 'https://authserver.example/', clientId: '...', // Note, if urls cannot be auto-detected, also specify these: tokenEndpoint: '/token', authorizationEndpoint: '/authorize', }); ``` -------------------------------- ### Initialize OAuth2 Client Configuration Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Configure the OAuth2Client with your server's base URI, client ID, and optionally client secret and endpoint URIs. If endpoint URIs are omitted, the client will attempt to discover them using the server's metadata document. ```typescript import { OAuth2Client } from '@badgateway/oauth2-client'; const client = new OAuth2Client({ // The base URI of your OAuth2 server server: 'https://my-auth-server/', // OAuth2 client id clientId: '...', // OAuth2 client secret. Only required for 'client_credentials', 'password' // flows. Don't specify this in insecure contexts, such as a browser using // the authorization_code flow. clientSecret: '...', // The following URIs are all optional. If they are not specified, we will // attempt to discover them using the oauth2 discovery document. // If your server doesn't have support this, you may need to specify these. // you may use relative URIs for any of these. // Token endpoint. Most flows need this. // If not specified we'll use the information for the discovery document // first, and otherwise default to /token tokenEndpoint: '/token', // Authorization endpoint. // // You only need this to generate URLs for authorization_code flows. // If not specified we'll use the information for the discovery document // first, and otherwise default to /authorize authorizationEndpoint: '/authorize', // OAuth2 Metadata discovery endpoint. // // This document is used to determine various server features. // If not specified, we assume it's on /.well-known/oauth2-authorization-server discoveryEndpoint: '/.well-known/oauth2-authorization-server', }); ``` -------------------------------- ### Create Fetch Middleware with OAuth2Client Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Utilize the `mw` function to create a fetch middleware for decorating existing request libraries. This allows integrating OAuth2 functionality into libraries like Ketting. ```typescript const mw = oauth2.mw(); const response = mw( myRequest, req => fetch(req) ); ``` ```typescript import { Client } from 'ketting'; import { OAuth2Client, OAuth2Fetch } from '@badgateway/oauth2-client'; /** * Create the oauth2 client */ const oauth2Client = new OAuth2Client({ server: 'https://my-auth.example', clientId: 'foo', }); /** * Create the 'fetch helper' */ const oauth2Fetch = new OAuth2Fetch({ client: oauth2Client, }); /** * Add the middleware to Ketting */ const ketting = new Client('http://api-root'); ketting.use(oauth2Fetch.mw()); ``` -------------------------------- ### Use Fetch Wrapper for API Requests Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Make API requests using the fetch wrapper. It automatically includes the Authorization header and handles token refreshing. ```typescript const response = fetchWrapper.fetch('https://my-api', { method: 'POST', body: 'Hello world' }); ``` -------------------------------- ### Generate PKCE Code Verifier Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Generates a security code verifier for PKCE, an advanced security feature. It's optional but recommended for enhanced security. ```typescript /** * This generates a security code that must be passed to the various steps. * This is used for 'PKCE' which is an advanced security feature. * * It doesn't break servers that don't support it, but it makes servers that * so support it more secure. * * It's optional to pass this, but recommended. */ const codeVerifier = await generateCodeVerifier(); ``` -------------------------------- ### Store and Retrieve OAuth2 Tokens with FetchWrapper Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Implement token storage and retrieval using localStorage to maintain user sessions between requests. The `storeToken` function is called when the token changes, and `getStoredToken` is used to fetch a previously stored token. ```typescript const fetchWrapper = new OAuth2Fetch({ client: client, getNewToken: async () => { // See above! }, /** * This function is called whenever the active token changes. Using this is * optional, but it may be used to (for example) put the token in off-line * storage for later usage. */ storeToken: (token) => { document.localStorage.setItem('token-store', JSON.stringify(token)); }, /** * Also an optional feature. Implement this if you want the wrapper to try a * stored token before attempting a full re-authentication. * * This function may be async. Return null if there was no token. */ getStoredToken: () => { const token = document.localStorage.getItem('token-store'); if (token) return JSON.parse(token); return null; } }); ``` -------------------------------- ### Configure OAuth2 Client Authentication Method Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Customize how the `client_id` and `client_secret` are encoded for authentication. Options include 'client_secret_post' (POST body), 'client_secret_basic' (strict Authorization header), and 'client_secret_basic_interop' (less strict Authorization header, default). ```typescript const client = new OAuth2Client({ server: 'https://auth-server.example/', clientId: '...', clientSecret: '...', authenticationMethod: 'client_secret_post', // encode in POST body }); ``` -------------------------------- ### Obtain Token using Password Grant Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Use the password method to obtain an access token by providing user credentials. This grant type should be used with caution and is not recommended for browser-based applications. ```typescript const token = await client.password({ username: '..', password: '..', }); ``` -------------------------------- ### Obtain Token using Client Credentials Grant Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Use the clientCredentials method to obtain an access token when the client is acting on its own behalf, typically for machine-to-machine communication. ```typescript const token = await client.clientCredentials(); ``` -------------------------------- ### Introspect OAuth2 Token with OAuth2Client Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Perform token introspection using the `introspect` method of the `OAuth2Client`. This requires the authorization server to support the introspection endpoint, whose location is discovered via metadata. ```typescript import { OAuth2Client } from '@badgateway/oauth2-client'; const client = new Client({ server: 'https://auth-server.example/', clientId: '...', /** * Some servers require OAuth2 clientId/clientSecret to be passed. * If they require it, specify it. If not it's fine to omit. */ clientSecret: '...', }); // Get a token const token = client.clientCredentials(); // Introspect! console.log(client.introspect(token)); ``` -------------------------------- ### OAuth2 Token Type Definition Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Defines the structure of an OAuth2 token, including access token, refresh token, expiration time, and optional ID token. ```typescript export type OAuth2Token = { accessToken: string; refreshToken: string | null; /** * When the Access Token expires. * * This is expressed as a unix timestamp in milliseconds. */ expiresAt: number | null; /** * If the server returned an OpenID Connect ID token, it will be stored here. */ idToken?: string; }; ``` -------------------------------- ### Refresh Expired OAuth2 Token Source: https://github.com/badgateway/oauth2-client/blob/main/README.md Call the refreshToken method with an existing token object to obtain a new access token. This is useful when the current access token has expired. ```typescript const newToken = await client.refreshToken(oldToken); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.