-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
87d8d13
commit 3348090
Showing
16 changed files
with
1,727 additions
and
905 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
# `OAuthService` | ||
|
||
The `OAuthService` class is designed to abstract the OAuth authorization process using the PKCE (Proof Key for Code Exchange) flow, simplifying the integration with various OAuth providers such as Asana, GitHub, and others. | ||
|
||
Use [OAuthServiceOptions](#OAuthServiceOptions) to configure the `OAuthService` class. | ||
|
||
## Signature | ||
|
||
```ts | ||
constructor(options: OAuthServiceOptions): OAuthService | ||
``` | ||
|
||
### Methods | ||
|
||
#### `authorize` | ||
|
||
Initiates the OAuth authorization process or refreshes existing tokens if necessary. Returns a promise that resolves with the access token from the authorization flow. | ||
|
||
##### Signature | ||
|
||
```typescript | ||
authorize(): Promise<string>; | ||
``` | ||
|
||
##### Example | ||
|
||
```typescript | ||
const accessToken = await oauthService.authorize(); | ||
``` | ||
|
||
### Properties | ||
|
||
Some 3rd-party providers are exposed by default to make it easy to authenticate with them. Here's the full list: | ||
|
||
- Asana | ||
- GitHub | ||
- Jira | ||
- Linear | ||
- Slack | ||
- Zoom | ||
|
||
#### Asana | ||
|
||
##### Signature | ||
|
||
```ts | ||
const asana: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const asana = OAuthService.asana({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: 'default', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
#### GitHub | ||
|
||
##### Signature | ||
|
||
```ts | ||
const github: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const github = OAuthService.github({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: 'repo user', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
|
||
##### Signature | ||
|
||
```ts | ||
const google: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const google = OAuthService.google({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: 'https://www.googleapis.com/auth/drive.readonly', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
#### Jira | ||
|
||
##### Signature | ||
|
||
```ts | ||
const jira: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const jira = OAuthService.jira({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: 'read:jira-user read:jira-work', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
#### Linear | ||
|
||
##### Signature | ||
|
||
```ts | ||
const linear: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const linear = OAuthService.linear({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: 'read write', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
#### Slack | ||
|
||
##### Signature | ||
|
||
```ts | ||
const slack: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const slack = OAuthService.slack({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: 'emoji:read', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
#### Zoom | ||
|
||
##### Signature | ||
|
||
```ts | ||
const zoom: OAuthService | ||
``` | ||
##### Example | ||
```tsx | ||
const zoom = OAuthService.zoom({ | ||
clientId: 'custom-client-id', // Optional: If omitted, defaults to a pre-configured client ID | ||
scope: '', // Specify the scopes your application requires | ||
personalAccessToken: 'personal-access-token', // Optional: For accessing the API directly | ||
}); | ||
``` | ||
|
||
## Example | ||
|
||
```ts | ||
const client = new OAuth.PKCEClient({ | ||
redirectMethod: OAuth.RedirectMethod.Web, | ||
providerName: "GitHub", | ||
providerIcon: "extension_icon.png", | ||
providerId: "github", | ||
description: "Connect your GitHub account", | ||
}); | ||
|
||
const github = new OAuthService({ | ||
client, | ||
clientId: "7235fe8d42157f1f38c0", | ||
scopes: "notifications repo read:org read:user read:project", | ||
authorizeUrl: "https://github.oauth.raycast.com/authorize", | ||
tokenUrl: "https://github.oauth.raycast.com/token", | ||
}); | ||
``` | ||
|
||
## Subclassing | ||
|
||
You can subclass `OAuthService` to create a tailored service for other OAuth providers by setting predefined defaults. | ||
|
||
Here's an example where `LinearOAuthService` subclasses `OAuthService`: | ||
|
||
```ts | ||
export class LinearOAuthService extends OAuthService { | ||
constructor(options: ClientConstructor) { | ||
super({ | ||
client: new OAuth.PKCEClient({ | ||
redirectMethod: OAuth.RedirectMethod.Web, | ||
providerName: "Linear", | ||
providerIcon: "linear.png", | ||
providerId: "linear", | ||
description: "Connect your Linear account", | ||
}), | ||
clientId: "YOUR_CLIENT_ID", | ||
authorizeUrl: "YOUR_AUTHORIZE_URL", | ||
tokenUrl: "YOUR_TOKEN_URL", | ||
scope: "YOUR_SCOPES" | ||
extraParameters: { | ||
actor: "user", | ||
}, | ||
}); | ||
} | ||
} | ||
``` | ||
|
||
## Types | ||
|
||
### OAuthServiceOptions | ||
Here's an updated markdown table with a "Type" column: | ||
|
||
| Property Name | Description | Type | | ||
|---------------|-------------|------| | ||
| `client` | The PKCE Client defined using `OAuth.PKCEClient` from `@raycast/api` | `OAuth.PKCEClient` | | ||
| `clientId` | The app's client ID | `string` | | ||
| `scope` | The scope of the access requested from the provider | `string` | | ||
| `authorizeUrl` | The URL to start the OAuth flow | `string` | | ||
| `tokenUrl` | The URL to exchange the authorization code for an access token | `string` | | ||
| `refreshTokenUrl` | (Optional) The URL to refresh the access token if applicable | `string` | | ||
| `personalAccessToken` | (Optional) A personal token if the provider supports it | `string` | | ||
| `extraParameters` | (Optional) The extra parameters you may need for the authorization request | `Record<string, string>` | | ||
| `bodyEncoding` | (Optional) Specifies the format for sending the body of the request. | `json` \| `url-encoded` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# OAuth | ||
|
||
Authenticating with OAuth in Raycast extensions is tedious. So we've built a set of utilities to make that task way easier. There's two part to our utilities: | ||
|
||
1. Authenticating with the service using [OAuthService](utils-reference/oauth/OAuthService.md) and providers we provide out of the box (e.g GitHub with `OAuthService.github`) | ||
2. Bringing authentication to React components using [withAccessToken](utils-reference/oauth/withAccessToken.md) and [`getAccessToken`](utils-reference/oauth/withAccessToken.md#getAccessToken) | ||
|
||
Here are two different use-cases where you can use the utilities. | ||
|
||
## Using a built-in provider | ||
|
||
We provide 3rd party providers that you can use out of the box such as GitHub or Linear. Here's how you can use them: | ||
|
||
```tsx | ||
import { Detail, LaunchProps } from "@raycast/api"; | ||
import { withAccessToken, getAccessToken, OAuthService } from "@raycast/utils"; | ||
|
||
const github = OAuthService.github({ | ||
scopes: "notifications repo read:org read:user read:project" | ||
}); | ||
|
||
function AuthorizedComponent(props: LaunchProps) { | ||
const { token } = getAccessToken(); | ||
return <Detail markdown={`Access token: ${token}`} />; | ||
} | ||
|
||
export default withAccessToken(github)(AuthorizedComponent); | ||
``` | ||
|
||
## Using your own client | ||
|
||
```tsx | ||
import { OAuth, Detail, LaunchProps } from "@raycast/api"; | ||
import { withAccessToken, getAccessToken, OAuthService } from "@raycast/utils/oauth"; | ||
|
||
const client = new OAuth.PKCEClient({ | ||
redirectMethod: OAuth.RedirectMethod.Web, | ||
providerName: "Your Provider Name", | ||
providerIcon: "provider_icon.png", | ||
providerId: "yourProviderId", | ||
description: "Connect your {PROVIDER_NAME} account", | ||
}); | ||
|
||
const provider = new OAuthService({ | ||
client, | ||
clientId: "YOUR_CLIENT_ID", | ||
scopes: "YOUR SCOPES", | ||
authorizeUrl: "YOUR_AUTHORIZE_URL", | ||
tokenUrl: "YOUR_TOKEN_URL", | ||
}); | ||
|
||
function AuthorizedComponent(props: LaunchProps) { | ||
const { token } = getAccessToken(); | ||
return <Detail markdown={`Access token: ${token}`} />; | ||
} | ||
|
||
export default withAccessToken({ authorize: provider.authorize })(AuthorizedComponent); | ||
``` | ||
|
||
## Additional information | ||
|
||
If you need more information, please take a look at the subpages: [OAuthService](utils-reference/oauth/OAuthService.md) and [withAccessToken](utils-reference/oauth/withAccessToken.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# `getAccessToken` | ||
|
||
Utility function designed for retrieving authorization tokens within a component. It ensures that your React components have the necessary authentication state, either through OAuth or a personal access token. | ||
|
||
{% hint style="info" %} | ||
`getAccessToken` **must** be used within components that are nested inside a component wrapped with [`withAccessToken`](utils-reference/oauth/withAccessToken.md). Otherwise, the function will fail with an error. | ||
{% endhint %} | ||
|
||
## Signature | ||
|
||
```tsx | ||
function getAccessToken(): { | ||
token: string; | ||
type: "oauth" | "personal"; | ||
} | ||
``` | ||
|
||
### Return | ||
|
||
The function returns an object containing the following properties: | ||
- `token`: A string representing the access token. | ||
- `type`: An optional string that indicates the type of token retrieved. It can either be `oauth` for OAuth tokens or `personal` for personal access tokens. | ||
|
||
## Example | ||
|
||
Here's a simple example: | ||
|
||
```tsx | ||
import { Detail } from "@raycast/api"; | ||
import { authorize } from "./oauth" | ||
|
||
function AuthorizedComponent() { | ||
const { token } = getAccessToken(); | ||
return <Detail markdown={`Access token: ${token}`} />; | ||
} | ||
|
||
export default withAccessToken({ authorize })(AuthorizedComponent); | ||
``` |
Oops, something went wrong.