From 79ce24bc6fb5079b226f64fe2a7558062be0e1f5 Mon Sep 17 00:00:00 2001 From: Jonas Franz Date: Sun, 14 Apr 2019 10:42:11 +0200 Subject: [PATCH] Add oauth2 documentation (#6604) * Add oauth2 documentation Signed-off-by: Jonas Franz * Apply suggestions from code review Co-Authored-By: jonasfranz * Update docs/content/doc/advanced/oauth2-provider.md Co-Authored-By: jonasfranz * Update oauth2-provider.md --- docs/content/doc/advanced/api-usage.en-us.md | 8 ++ docs/content/doc/advanced/oauth2-provider.md | 92 +++++++++++++++++++ docs/static/authorize.png | Bin 0 -> 18951 bytes 3 files changed, 100 insertions(+) create mode 100644 docs/content/doc/advanced/oauth2-provider.md create mode 100644 docs/static/authorize.png diff --git a/docs/content/doc/advanced/api-usage.en-us.md b/docs/content/doc/advanced/api-usage.en-us.md index d5a7b3a6ef..c5db817fdb 100644 --- a/docs/content/doc/advanced/api-usage.en-us.md +++ b/docs/content/doc/advanced/api-usage.en-us.md @@ -39,6 +39,14 @@ Gitea parses queries and headers to find the token in You can create an API key token via your Gitea installation's web interface: `Settings | Applications | Generate New Token`. +### OAuth2 + +Access tokens obtained from Gitea's [OAuth2 provider](https://docs.gitea.io/en-us/oauth2-provider) are accepted by these methods: + +- `Authorization bearer ...` header in HTTP headers +- `token=...` parameter in URL query string +- `access_token=...` parameter in URL query string + ### More on the `Authorization:` header For historical reasons, Gitea needs the word `token` included before diff --git a/docs/content/doc/advanced/oauth2-provider.md b/docs/content/doc/advanced/oauth2-provider.md new file mode 100644 index 0000000000..c924d1ce07 --- /dev/null +++ b/docs/content/doc/advanced/oauth2-provider.md @@ -0,0 +1,92 @@ +--- +date: "2019-04-19:44:00+01:00" +title: "OAuth2 provider" +slug: "oauth2-provider" +weight: 41 +toc: true +draft: false +menu: + sidebar: + parent: "advanced" + name: "OAuth2 Provider" + weight: 41 + identifier: "oauth2-provider" +--- + + +# OAuth2 provider + +Gitea supports acting as an OAuth2 provider to allow third party applications to access its resources with the user's consent. This feature is available since release 1.8.0. + +## Endpoints + + +Endpoint | URL +-----------------------|---------------------------- +Authorization Endpoint | `/login/oauth/authorize` +Access Token Endpoint | `/login/oauth/access_token` + + +## Supported OAuth2 Grants + +At the moment Gitea only supports the [**Authorization Code Grant**](https://tools.ietf.org/html/rfc6749#section-1.3.1) standard with additional support of the [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636) extension. + + +To use the Authorization Code Grant as a third party application it is required to register a new application via the "Settings" (`/user/settings/applications`) section of the settings. + +## Scopes + +Currently Gitea does not support scopes (see [#4300](https://github.com/go-gitea/gitea/issues/4300)) and all third party applications will be granted access to all resources of the user and his/her organizations. + +## Example + +**Note:** This example does not use PKCE. + +1. Redirect to user to the authorization endpoint in order to get his/her consent for accessing the resources: + +```curl +https://[YOUR-GITEA-URL]/login/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI& response_type=code&state=STATE +``` + +The `CLIENT_ID` can be obtained by registering an application in the settings. The `STATE` is a random string that will be send back to your application after the user authorizes. The `state` parameter is optional but should be used to prevent CSRF attacks. + + +![Authorization Page](/authorize.png) + +The user will now be asked to authorize your application. If they authorize it, the user will be redirected to the `REDIRECT_URL`, for example: + +```curl +https://[REDIRECT_URI]?code=RETURNED_CODE&state=STATE +``` + +2. Using the provided `code` from the redirect, you can request a new application and refresh token. The access token endpoints accepts POST requests with `application/json` and `application/x-www-form-urlencoded` body, for example: + +```curl +POST https://[YOUR-GITEA-URL]/login/oauth/access_token +``` + +```json +{ + "client_id": "YOUR_CLIENT_ID", + "client_secret": "YOUR_CLIENT_SECRET", + "code": "RETURNED_CODE", + "grant_type": "authorization_code", + "redirect_uri": "REDIRECT_URI" +} +``` + +Response: +```json +{ +"access_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJnbnQiOjIsInR0IjowLCJleHAiOjE1NTUxNzk5MTIsImlhdCI6MTU1NTE3NjMxMn0.0-iFsAwBtxuckA0sNZ6QpBQmywVPz129u75vOM7wPJecw5wqGyBkmstfJHAjEOqrAf_V5Z-1QYeCh_Cz4RiKug", +"token_type":"bearer", +"expires_in":3600, +"refresh_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJnbnQiOjIsInR0IjoxLCJjbnQiOjEsImV4cCI6MTU1NzgwNDMxMiwiaWF0IjoxNTU1MTc2MzEyfQ.S_HZQBy4q9r5SEzNGNIoFClT43HPNDbUdHH-GYNYYdkRfft6XptJBkUQscZsGxOW975Yk6RbgtGvq1nkEcklOw" +} +``` + +The `CLIENT_SECRET` is the unique secret code generated for this application. Please note that the secret will only be visible after you created/registered the application with Gitea and cannot be recovered. If you lose the secret you must regenerate the secret via the application's settings. + +The `REDIRECT_URI` in the `access_token` request must match the `REDIRECT_URI` in the `authorize` request. + +3. Use the `access_token` to make [API requests](https://docs.gitea.io/en-us/api-usage#oauth2) to access the user's resources. diff --git a/docs/static/authorize.png b/docs/static/authorize.png new file mode 100644 index 0000000000000000000000000000000000000000..7556b1220cd21c0c7b08cbb2ff99b7af91043397 GIT binary patch literal 18951 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 e3K%7iEef$xg{Nuk}A*Yf6 literal 0 HcmV?d00001