OAuth
Last updated
Last updated
A Raycast extension can use OAuth for authorizing access to a provider's resources on the user's behalf. Since Raycast is a desktop app and the extensions are considered "public", we only support the PKCE flow (Proof Key for Code Exchange, pronounced “pixy”). This flow is the official recommendation for native clients that cannot keep a client secret. With PKCE, the client dynamically creates a secret and uses the secret again during code exchange, ensuring that only the client that performed the initial request can exchange the code for the access token (”proof of possession”).
Providers such as Google, Twitter, GitLab, Spotify, Zoom, Asana or Dropbox are all PKCE-ready.
However, if your provider doesn't support PKCE, you can use our PKCE proxy. It allows extensions to securely use an OAuth flow without exposing any secret.
The OAuth flow from an extension looks like this:
The extension initiates the OAuth flow and starts authorization
Raycast shows the OAuth overlay ("Connect to provider…")
The user opens the provider's consent page in the web browser
After the user consent, the provider redirects back to Raycast
Raycast opens the extension where authorization is completed
When the flow is complete, the extension has received an access token from the provider and can perform API calls. The API provides functions for securely storing and retrieving token sets, so that an extension can check whether the user is already logged in and whether an expired access token needs to be refreshed. Raycast also automatically shows a logout preference.
You first need to register a new OAuth app with your provider. This is usually done in the provider's developer portal. After registering, you will receive a client ID. You also need to configure a redirect URI, see the next section.
Note: Make sure to choose an app type that supports PKCE. Some providers still show you a client secret, which you don't need and should not hardcode in the extension, or support PKCE only for certain types such as "desktop", "native" or "mobile" app types.
An extension can initiate the OAuth flow and authorize by using the methods on OAuth.PKCEClient.
You can create a new client and configure it with a provider name, icon and description that will be shown in the OAuth overlay. You can also choose between different redirect methods; depending on which method you choose, you need to configure this value as redirect URI in your provider's registered OAuth app. (See the OAuth.RedirectMethod docs for each method to get concrete examples for supported redirect URI.) If you can choose, use OAuth.RedirectMethod.Web
and enter https://raycast.com/redirect?packageName=Extension
(whether you have to add the ?packageName=Extension
depends on the provider).
Next you create an authorization request with the authorization endpoint, client ID, and scope values. You receive all values from your provider's docs and when you register a new OAuth app.
The returned AuthorizationRequest contains parameters such as the code challenge, verifier, state and redirect URI as standard OAuth authorization request. You can also customize the authorization URL through OAuth.AuthorizationOptions if you need to.
To get the authorization code needed for the token exchange, you call authorize with the request from the previous step. This call shows the Raycast OAuth overlay and provides the user with an option to open the consent page in the web browser. The authorize promise is resolved after the redirect back to Raycast and into the extension:
When in development mode, make sure not to trigger auto-reloading (e.g. by saving a file) while you're testing an active OAuth authorization and redirect. This would cause an OAuth state mismatch when you're redirected back into the extension since the client would be reinitialized on reload.
Now that you have received the authorization code, you can exchange this code for an access token using your provider's token endpoint. This token exchange (and the following API calls) can be done with your preferred Node HTTP client library. Example using node-fetch
:
The PKCE client exposes methods for storing, retrieving and deleting token sets. A TokenSet contains an access token and typically also a refresh token, expires value, and the current scope. Since this data is returned by the provider's token endpoint as standard OAuth JSON response, you can directly store the response (OAuth.TokenResponse) or alternatively use OAuth.TokenSetOptions:
Once the token set is stored, Raycast will automatically show a logout preference for the extension. When the user logs out, the token set gets removed.
The TokenSet also enables you to check whether the user is logged in before starting the authorization flow:
Since access tokens usually expire, an extension should provide a way to refresh the access token, otherwise users would be logged out or see errors. Some providers require you to add an offline scope so that you get a refresh token. (Twitter, for example, needs the scope offline.access
or it only returns an access token.) A basic refresh flow could look like this:
This code would run before starting the authorization flow. It checks the presence of a token set to see whether the user is logged in and then checks whether there is a refresh token and the token set is expired (through the convenience method isExpired()
on the TokenSet). If it is expired, the token is refreshed and updated in the token set. Example using node-fetch
:
We've provided OAuth example integrations for Google, Twitter, and Dropbox that demonstrate the entire flow shown above.
Use OAuth.PKCEClient.Options to configure what's shown on the OAuth overlay.
Creates an authorization request for the provided authorization endpoint, client ID, and scopes. You need to first create the authorization request before calling authorize.
The generated code challenge for the PKCE request uses the S256 method.
options*
The options used to create the authorization request.
A promise for an AuthorizationRequest that you can use as input for authorize.
Starts the authorization and shows the OAuth overlay in Raycast. As parameter you can either directly use the returned request from authorizationRequest, or customize the URL by extracting parameters from AuthorizationRequest and providing your own URL via AuthorizationOptions. Eventually the URL will be used to open the authorization page of the provider in the web browser.
options*
The options used to authorize.
A promise for an AuthorizationResponse, which contains the authorization code needed for the token exchange. The promise is resolved when the user was redirected back from the provider's authorization page to the Raycast extension.
Securely stores a TokenSet for the provider. Use this after fetching the access token from the provider. If the provider returns a a standard OAuth JSON token response, you can directly pass the TokenResponse. At a minimum, you need to set the accessToken
, and typically you also set refreshToken
and isExpired
.
Raycast automatically shows a logout preference for the extension when a token set was saved.
If you want to make use of the convenience isExpired()
method, the property expiresIn
must be configured.
options*
The options used to store the token set.
A promise that resolves when the token set has been stored.
Retrieves the stored TokenSet for the client. You can use this to initially check whether the authorization flow should be initiated or the user is already logged in and you might have to refresh the access token.
A promise that resolves when the token set has been retrieved.
Removes the stored TokenSet for the client. Raycast automatically shows a logout preference that removes the token set. Use this method only if you need to provide an additional logout option in your extension or you want to remove the token set because of a migration.
A promise that resolves when the token set has been removed.
The options for creating a new PKCEClient.
providerName*
The name of the provider, displayed in the OAuth overlay.
string
redirectMethod*
description
An optional description, shown in the OAuth overlay. You can use this to customize the message for the end user, for example for handling scope changes or other migrations. Raycast shows a default message if this is not configured.
string
providerIcon
An icon displayed in the OAuth overlay. Make sure to provide at least a size of 64x64 pixels.
providerId
An optional ID for associating the client with a provider. Only set this if you use multiple different clients in your extension.
string
Defines the supported redirect methods for the OAuth flow. You can choose between web and app-scheme redirect methods, depending on what the provider requires when setting up the OAuth app. For examples on what redirect URI you need to configure, see the docs for each method.
Web
App
Use this type for an app-scheme based redirect that directly opens Raycast. In the OAuth app, configure raycast://oauth?package_name=Extension
AppURI
Use this type for a URI-style app scheme that directly opens Raycast. In the OAuth app, configure com.raycast:/oauth?package_name=Extension
(Note the single slash – Google, for example, would require this flavor for an OAuth app where the Bundle ID is com.raycast
)
The options for an authorization request via authorizationRequest.
clientId*
The client ID of the configured OAuth app.
string
endpoint*
The URL to the authorization endpoint for the OAuth provider.
string
scope*
A space-delimited list of scopes for identifying the resources to access on the user's behalf. The scopes are typically shown to the user on the provider's consent screen in the browser. Note that some providers require the same scopes be configured in the registered OAuth app.
string
extraParameters
Optional additional parameters for the authorization request. Note that some providers require additional parameters, for example to obtain long-lived refresh tokens.
Record<string, string>
Values of AuthorizationRequest. The PKCE client automatically generates the values for you and returns them for authorizationRequest
codeChallenge*
The PKCE code_challenge
value.
string
codeVerifier*
The PKCE code_verifier
value.
string
redirectURI*
The OAuth redirect_uri
value.
string
state*
The OAuth state
value.
string
The request returned by authorizationRequest. Can be used as direct input to authorize, or to extract parameters for constructing a custom URL in AuthorizationOptions.
codeChallenge*
The PKCE code_challenge
value.
string
codeVerifier*
The PKCE code_verifier
value.
string
redirectURI*
The OAuth redirect_uri
value.
string
state*
The OAuth state
value.
string
toURL*
Constructs the full authorization URL.
() => string
toURL()
() => string
Constructs the full authorization URL.
Options for customizing authorize. You can use values from AuthorizationRequest to build your own URL.
url*
The full authorization URL.
string
The response returned by authorize, containing the authorization code after the provider redirect. You can then exchange the authorization code for an access token using the provider's token endpoint.
authorizationCode*
The authorization code from the OAuth provider.
string
Describes the TokenSet created from an OAuth provider's token response. The accessToken
is the only required parameter but typically OAuth providers also return a refresh token, an expires value, and the scope. Securely store a token set via setTokens and retrieve it via getTokens.
accessToken*
The access token returned by an OAuth token request.
string
updatedAt*
Date
isExpired*
A convenience method for checking whether the access token has expired. The method factors in some seconds of "buffer", so it returns true a couple of seconds before the actual expiration time. This requires the expiresIn
parameter to be set.
() => boolean
expiresIn
An optional expires value (in seconds) returned by an OAuth token request.
number
idToken
An optional id token returned by an identity request (e.g. /me, Open ID Connect).
string
refreshToken
An optional refresh token returned by an OAuth token request.
string
scope
The optional space-delimited list of scopes returned by an OAuth token request. You can use this to compare the currently stored access scopes against new access scopes the extension might require in a future version, and then ask the user to re-authorize with new scopes.
string
isExpired()
() => boolean
A convenience method for checking whether the access token has expired. The method factors in some seconds of "buffer", so it returns true a couple of seconds before the actual expiration time. This requires the expiresIn
parameter to be set.
Options for a TokenSet to store via setTokens.
accessToken*
The access token returned by an OAuth token request.
string
expiresIn
An optional expires value (in seconds) returned by an OAuth token request.
number
idToken
An optional id token returned by an identity request (e.g. /me, Open ID Connect).
string
refreshToken
An optional refresh token returned by an OAuth token request.
string
scope
The optional scope value returned by an OAuth token request.
string
Defines the standard JSON response for an OAuth token request. The response can be directly used to store a TokenSet via setTokens.
access_token*
The access_token
value returned by an OAuth token request.
string
expires_in
An optional expires_in
value (in seconds) returned by an OAuth token request.
number
id_token
An optional id_token
value returned by an identity request (e.g. /me, Open ID Connect).
string
refresh_token
An optional refresh_token
value returned by an OAuth token request.
string
scope
The optional scope
value returned by an OAuth token request.
string
|
|
The redirect method for the OAuth flow. Make sure to set this to the correct method for the provider, see for more information.
Use this type for a redirect back to the Raycast website, which will then open the extension. In the OAuth app, configure https://raycast.com/redirect?packageName=Extension
(This is a static redirect URL for all extensions.)
If the provider does not accept query parameters in redirect URLs, you can alternatively use https://raycast.com/redirect/extension
and then customize the via its extraParameters
property. For example add: extraParameters: { "redirect_uri": "https://raycast.com/redirect/extension" }
The date when the token set was stored via .