mirror of https://github.com/coder/coder.git
feat: add endpoints to oauth2 provider applications (#11718)
These will show up when configuring the application along with the client ID and everything else. Should make it easier to configure the application, otherwise you will have to go look up the URLs in the docs (which are not yet written). Co-authored-by: Steven Masley <stevenmasley@gmail.com>
This commit is contained in:
parent
8e0a153725
commit
3014777d2a
|
@ -9688,6 +9688,21 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"codersdk.OAuth2AppEndpoints": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authorization": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_authorization": {
|
||||
"description": "DeviceAuth is optional.",
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.OAuth2Config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -9734,6 +9749,14 @@ const docTemplate = `{
|
|||
"callback_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"endpoints": {
|
||||
"description": "Endpoints are included in the app response for easier discovery. The OAuth2\nspec does not have a defined place to find these (for comparison, OIDC has\na '/.well-known/openid-configuration' endpoint).",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.OAuth2AppEndpoints"
|
||||
}
|
||||
]
|
||||
},
|
||||
"icon": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
@ -8683,6 +8683,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"codersdk.OAuth2AppEndpoints": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authorization": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_authorization": {
|
||||
"description": "DeviceAuth is optional.",
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.OAuth2Config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -8729,6 +8744,14 @@
|
|||
"callback_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"endpoints": {
|
||||
"description": "Endpoints are included in the app response for easier discovery. The OAuth2\nspec does not have a defined place to find these (for comparison, OIDC has\na '/.well-known/openid-configuration' endpoint).",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.OAuth2AppEndpoints"
|
||||
}
|
||||
]
|
||||
},
|
||||
"icon": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@ package db2sdk
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -226,19 +227,29 @@ func templateVersionParameterOptions(rawOptions json.RawMessage) ([]codersdk.Tem
|
|||
return options, nil
|
||||
}
|
||||
|
||||
func OAuth2ProviderApp(dbApp database.OAuth2ProviderApp) codersdk.OAuth2ProviderApp {
|
||||
func OAuth2ProviderApp(accessURL *url.URL, dbApp database.OAuth2ProviderApp) codersdk.OAuth2ProviderApp {
|
||||
return codersdk.OAuth2ProviderApp{
|
||||
ID: dbApp.ID,
|
||||
Name: dbApp.Name,
|
||||
CallbackURL: dbApp.CallbackURL,
|
||||
Icon: dbApp.Icon,
|
||||
Endpoints: codersdk.OAuth2AppEndpoints{
|
||||
Authorization: accessURL.ResolveReference(&url.URL{
|
||||
Path: "/login/oauth2/authorize",
|
||||
}).String(),
|
||||
Token: accessURL.ResolveReference(&url.URL{
|
||||
Path: "/login/oauth2/tokens",
|
||||
}).String(),
|
||||
// We do not currently support DeviceAuth.
|
||||
DeviceAuth: "",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func OAuth2ProviderApps(dbApps []database.OAuth2ProviderApp) []codersdk.OAuth2ProviderApp {
|
||||
func OAuth2ProviderApps(accessURL *url.URL, dbApps []database.OAuth2ProviderApp) []codersdk.OAuth2ProviderApp {
|
||||
apps := []codersdk.OAuth2ProviderApp{}
|
||||
for _, dbApp := range dbApps {
|
||||
apps = append(apps, OAuth2ProviderApp(dbApp))
|
||||
apps = append(apps, OAuth2ProviderApp(accessURL, dbApp))
|
||||
}
|
||||
return apps
|
||||
}
|
||||
|
|
|
@ -14,6 +14,18 @@ type OAuth2ProviderApp struct {
|
|||
Name string `json:"name"`
|
||||
CallbackURL string `json:"callback_url"`
|
||||
Icon string `json:"icon"`
|
||||
|
||||
// Endpoints are included in the app response for easier discovery. The OAuth2
|
||||
// spec does not have a defined place to find these (for comparison, OIDC has
|
||||
// a '/.well-known/openid-configuration' endpoint).
|
||||
Endpoints OAuth2AppEndpoints `json:"endpoints"`
|
||||
}
|
||||
|
||||
type OAuth2AppEndpoints struct {
|
||||
Authorization string `json:"authorization"`
|
||||
Token string `json:"token"`
|
||||
// DeviceAuth is optional.
|
||||
DeviceAuth string `json:"device_authorization"`
|
||||
}
|
||||
|
||||
// OAuth2ProviderApps returns the applications configured to authenticate using
|
||||
|
|
|
@ -454,6 +454,11 @@ curl -X GET http://coder-server:8080/api/v2/oauth2-provider/apps \
|
|||
[
|
||||
{
|
||||
"callback_url": "string",
|
||||
"endpoints": {
|
||||
"authorization": "string",
|
||||
"device_authorization": "string",
|
||||
"token": "string"
|
||||
},
|
||||
"icon": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"name": "string"
|
||||
|
@ -471,13 +476,17 @@ curl -X GET http://coder-server:8080/api/v2/oauth2-provider/apps \
|
|||
|
||||
Status Code **200**
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ---------------- | ------------ | -------- | ------------ | ----------- |
|
||||
| `[array item]` | array | false | | |
|
||||
| `» callback_url` | string | false | | |
|
||||
| `» icon` | string | false | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» name` | string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ------------------------- | -------------------------------------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `[array item]` | array | false | | |
|
||||
| `» callback_url` | string | false | | |
|
||||
| `» endpoints` | [codersdk.OAuth2AppEndpoints](schemas.md#codersdkoauth2appendpoints) | false | | Endpoints are included in the app response for easier discovery. The OAuth2 spec does not have a defined place to find these (for comparison, OIDC has a '/.well-known/openid-configuration' endpoint). |
|
||||
| `»» authorization` | string | false | | |
|
||||
| `»» device_authorization` | string | false | | Device authorization is optional. |
|
||||
| `»» token` | string | false | | |
|
||||
| `» icon` | string | false | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» name` | string | false | | |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
|
@ -518,6 +527,11 @@ curl -X POST http://coder-server:8080/api/v2/oauth2-provider/apps \
|
|||
```json
|
||||
{
|
||||
"callback_url": "string",
|
||||
"endpoints": {
|
||||
"authorization": "string",
|
||||
"device_authorization": "string",
|
||||
"token": "string"
|
||||
},
|
||||
"icon": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"name": "string"
|
||||
|
@ -558,6 +572,11 @@ curl -X GET http://coder-server:8080/api/v2/oauth2-provider/apps/{app} \
|
|||
```json
|
||||
{
|
||||
"callback_url": "string",
|
||||
"endpoints": {
|
||||
"authorization": "string",
|
||||
"device_authorization": "string",
|
||||
"token": "string"
|
||||
},
|
||||
"icon": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"name": "string"
|
||||
|
@ -610,6 +629,11 @@ curl -X PUT http://coder-server:8080/api/v2/oauth2-provider/apps/{app} \
|
|||
```json
|
||||
{
|
||||
"callback_url": "string",
|
||||
"endpoints": {
|
||||
"authorization": "string",
|
||||
"device_authorization": "string",
|
||||
"token": "string"
|
||||
},
|
||||
"icon": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"name": "string"
|
||||
|
|
|
@ -3519,6 +3519,24 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
| `id` | string | true | | |
|
||||
| `username` | string | true | | |
|
||||
|
||||
## codersdk.OAuth2AppEndpoints
|
||||
|
||||
```json
|
||||
{
|
||||
"authorization": "string",
|
||||
"device_authorization": "string",
|
||||
"token": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ---------------------- | ------ | -------- | ------------ | --------------------------------- |
|
||||
| `authorization` | string | false | | |
|
||||
| `device_authorization` | string | false | | Device authorization is optional. |
|
||||
| `token` | string | false | | |
|
||||
|
||||
## codersdk.OAuth2Config
|
||||
|
||||
```json
|
||||
|
@ -3572,6 +3590,11 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
```json
|
||||
{
|
||||
"callback_url": "string",
|
||||
"endpoints": {
|
||||
"authorization": "string",
|
||||
"device_authorization": "string",
|
||||
"token": "string"
|
||||
},
|
||||
"icon": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"name": "string"
|
||||
|
@ -3580,12 +3603,13 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| -------------- | ------ | -------- | ------------ | ----------- |
|
||||
| `callback_url` | string | false | | |
|
||||
| `icon` | string | false | | |
|
||||
| `id` | string | false | | |
|
||||
| `name` | string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| -------------- | ---------------------------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `callback_url` | string | false | | |
|
||||
| `endpoints` | [codersdk.OAuth2AppEndpoints](#codersdkoauth2appendpoints) | false | | Endpoints are included in the app response for easier discovery. The OAuth2 spec does not have a defined place to find these (for comparison, OIDC has a '/.well-known/openid-configuration' endpoint). |
|
||||
| `icon` | string | false | | |
|
||||
| `id` | string | false | | |
|
||||
| `name` | string | false | | |
|
||||
|
||||
## codersdk.OAuth2ProviderAppSecret
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ func (api *API) oAuth2ProviderApps(rw http.ResponseWriter, r *http.Request) {
|
|||
httpapi.InternalServerError(rw, err)
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApps(dbApps))
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApps(api.AccessURL, dbApps))
|
||||
}
|
||||
|
||||
// @Summary Get OAuth2 application.
|
||||
|
@ -65,10 +65,10 @@ func (api *API) oAuth2ProviderApps(rw http.ResponseWriter, r *http.Request) {
|
|||
// @Param app path string true "App ID"
|
||||
// @Success 200 {object} codersdk.OAuth2ProviderApp
|
||||
// @Router /oauth2-provider/apps/{app} [get]
|
||||
func (*API) oAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *API) oAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
app := httpmw.OAuth2ProviderApp(r)
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApp(app))
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApp(api.AccessURL, app))
|
||||
}
|
||||
|
||||
// @Summary Create OAuth2 application.
|
||||
|
@ -101,7 +101,7 @@ func (api *API) postOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusCreated, db2sdk.OAuth2ProviderApp(app))
|
||||
httpapi.Write(ctx, rw, http.StatusCreated, db2sdk.OAuth2ProviderApp(api.AccessURL, app))
|
||||
}
|
||||
|
||||
// @Summary Update OAuth2 application.
|
||||
|
@ -135,7 +135,7 @@ func (api *API) putOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApp(app))
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApp(api.AccessURL, app))
|
||||
}
|
||||
|
||||
// @Summary Delete OAuth2 application.
|
||||
|
|
|
@ -656,6 +656,13 @@ export interface MinimalUser {
|
|||
readonly avatar_url: string;
|
||||
}
|
||||
|
||||
// From codersdk/oauth2.go
|
||||
export interface OAuth2AppEndpoints {
|
||||
readonly authorization: string;
|
||||
readonly token: string;
|
||||
readonly device_authorization: string;
|
||||
}
|
||||
|
||||
// From codersdk/deployment.go
|
||||
export interface OAuth2Config {
|
||||
readonly github: OAuth2GithubConfig;
|
||||
|
@ -678,6 +685,7 @@ export interface OAuth2ProviderApp {
|
|||
readonly name: string;
|
||||
readonly callback_url: string;
|
||||
readonly icon: string;
|
||||
readonly endpoints: OAuth2AppEndpoints;
|
||||
}
|
||||
|
||||
// From codersdk/oauth2.go
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useTheme } from "@emotion/react";
|
||||
import { type Interpolation, type Theme, useTheme } from "@emotion/react";
|
||||
import CopyIcon from "@mui/icons-material/FileCopyOutlined";
|
||||
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft";
|
||||
import Divider from "@mui/material/Divider";
|
||||
|
@ -139,16 +139,28 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
|
|||
onCancel={() => setShowDelete(false)}
|
||||
/>
|
||||
|
||||
<h2 css={{ marginBottom: 0 }}>Client ID</h2>
|
||||
<CopyableValue value={app.id}>
|
||||
{app.id}{" "}
|
||||
<CopyIcon
|
||||
css={{
|
||||
width: 16,
|
||||
height: 16,
|
||||
}}
|
||||
/>
|
||||
</CopyableValue>
|
||||
<dl css={styles.dataList}>
|
||||
<dt>Client ID</dt>
|
||||
<dd>
|
||||
<CopyableValue value={app.id}>
|
||||
{app.id} <CopyIcon css={{ width: 16, height: 16 }} />
|
||||
</CopyableValue>
|
||||
</dd>
|
||||
<dt>Authorization URL</dt>
|
||||
<dd>
|
||||
<CopyableValue value={app.endpoints.authorization}>
|
||||
{app.endpoints.authorization}{" "}
|
||||
<CopyIcon css={{ width: 16, height: 16 }} />
|
||||
</CopyableValue>
|
||||
</dd>
|
||||
<dt>Token URL</dt>
|
||||
<dd>
|
||||
<CopyableValue value={app.endpoints.token}>
|
||||
{app.endpoints.token}{" "}
|
||||
<CopyIcon css={{ width: 16, height: 16 }} />
|
||||
</CopyableValue>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<Divider css={{ borderColor: theme.palette.divider }} />
|
||||
|
||||
|
@ -303,3 +315,16 @@ const OAuth2SecretRow: FC<OAuth2SecretRowProps> = ({
|
|||
</TableRow>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
dataList: {
|
||||
display: "grid",
|
||||
gridTemplateColumns: "max-content auto",
|
||||
"& > dt": {
|
||||
fontWeight: "bold",
|
||||
},
|
||||
"& > dd": {
|
||||
marginLeft: 10,
|
||||
},
|
||||
},
|
||||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
|
|
@ -3371,6 +3371,11 @@ export const MockOAuth2ProviderApps: TypesGen.OAuth2ProviderApp[] = [
|
|||
name: "foo",
|
||||
callback_url: "http://localhost:3001",
|
||||
icon: "/icon/github.svg",
|
||||
endpoints: {
|
||||
authorization: "http://localhost:3001/login/oauth2/authorize",
|
||||
token: "http://localhost:3001/login/oauth2/token",
|
||||
device_authorization: "",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
|
Loading…
Reference in New Issue