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 d5a7b3a6e..c5db817fd 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 000000000..c924d1ce0 --- /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 zcmce;WmH_vvpzb*z@QTdfdB&mCcz2rZov~QNN@=5?gS<{1P|^G2@u>hIKkaLxVyuh zN5&!^fMf?b$fe}wq zXv-@B0CIrz8xdvKl>Mf|FT|UfmkZvMOmTfSdv0sYwu5bvguIo4{J)xP@SczUT$ZR^ zA>Z6EGpfb(iF;$lqS}kDYG;SI-9 zMoH7C`@UB?0o$uEiBnmP-ok}zuVvZQ)De!UlDcMx`-Hk?R8ce-g^#CA!z*Dln4cvo zyD;KGlpk0M@i=-IfDZF}g9{~x`9(^xmI5E{554ngLb3|1#xU7hMP8oYT|0zi(S*#F z>-fRkq2!Qo#4kz8VQpx)Sj;_VX#yUT`2z#*{tSWE&GS?DU6C{uxx*c*KWhf$$5h{V&>k{&PqQrK8*6FVdoGOL7`ql@;{B9>X-Ds#BKS@E3NlRT_U{WEk(A_B; zJ^d9@RaMntOHNwEc=Nf+@^YW+Ya6@!8wkJG9U(C>aT?W@1>9?6%Dl?%_JZX3^8+gn zpFd-N{rEEu@kpciLV;@904{gxaboyls$@wxdt~~;@6SqNwCU;T3shU$zEbc0pd$PQ zNNs9yo?~vQs^ZXUaQ-y+Oj;2!%DUcppLcR{^5}Oj@9h4Ca8v7{+xf#E0VT4fK{*K3 zQmIb;(3Z>|=~(NIKs`XYAku4C=(@S#B^7Y@i;cyHl8YaY8gY{!7R1^y zgR34MZja@E(6!OGvVw$3fG!W2M*ia+yT=DyXc!nFZE5r34xyd`(~-yEwb1R6Nt0JP zSPHS6cSS$68^Yc1y@r@gr`=i)&j%l8AV;vBbMb$P$%J$!wW^g>#G&hG& zOsMd?mil;HHfIC>=>+Yf%Uh7Ya8$2|Hx7K8lXV*BT!S6fsjrQ%n{F=SP z(|nUWW)6<9{&n$`G>%ga;oC6+7qi5`-h6@t>yRYCfG&Snb_HswH{z=vmusziEGc#T z8_sk&ZG;(94RF3u08@UxRoLDK8r!_c25HFRWPe? zNh6s{q77wwb=>oiq_=M4y0`85+8!o$#$F9;{GuRsK_7u_uzz^!CJ3||YcrA{K=U{)x^PIf6bnA~O z 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 Lc_z1&&bj#yT_LBE literal 0 HcmV?d00001