docs: update go authorization example to the new version (#7015)

* docs: update go authorization example to the new version

* fix reference to code
This commit is contained in:
Livio Spring
2023-12-06 18:32:43 +02:00
committed by GitHub
parent 970c062307
commit a87f54b328
6 changed files with 135 additions and 82 deletions

View File

@@ -8,9 +8,26 @@ OAuth 2 Token Introspection.
At the end of the guide you should have an API with a protected endpoint. At the end of the guide you should have an API with a protected endpoint.
> This documentation references our HTTP example. There's also one for GRPC. Check them out on [GitHub](https://github.com/zitadel/zitadel-go/tree/authorization/example/api).
## Set up application and obtain keys
Before we begin developing our API, we need to perform a few configuration steps in the ZITADEL Console.
You'll need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your Project, then add a new application at the top of the page.
Select the **API** application type and continue.
![Create app in console](/img/go/api-create.png)
We recommend that you use JWT Profile for authenticating at the Introspection Endpoint.
![Create app in console](/img/go/api-create-auth.png)
Then create a new key with your desired expiration date. Be sure to download it, as you won't be able to retrieve it again.
![Create api key in console](/img/go/api-create-key.png)
## Prerequisites ## Prerequisites
The client [SDK](https://github.com/zitadel/zitadel-go) will provides an interceptor for both GRPC and HTTP.
This will handle the OAuth 2.0 introspection request including authentication using JWT with Private Key using our [OIDC client library](https://github.com/zitadel/oidc). This will handle the OAuth 2.0 introspection request including authentication using JWT with Private Key using our [OIDC client library](https://github.com/zitadel/oidc).
All that is required, is to create your API and download the private key file later called `Key JSON` for the service user. All that is required, is to create your API and download the private key file later called `Key JSON` for the service user.
@@ -18,134 +35,170 @@ All that is required, is to create your API and download the private key file la
### Add Go SDK to your project ### Add Go SDK to your project
You need to add the SDK into Go Modules by: You need to add the [SDK](https://github.com/zitadel/zitadel-go) into Go Modules by:
```bash ```bash
go get github.com/zitadel/zitadel-go/v2 go get -u github.com/zitadel/zitadel-go/v3
``` ```
### Create example API ### Create example API
Create a new go file with the content below. This will create an API with two endpoints. On path `/public` it will always write Create a new go file with the content below. This will create an API with three endpoints:
back `ok` and the current timestamp. On `/protected` it will respond the same but only if a valid access_token is sent. The token - `/api/healthz`: can be called by anyone and always returns `OK`
must not be expired and the API has to be part of the audience (either client_id or project_id). - `/api/tasks`: requires authorization and returns the available tasks
- `/api/add-task`: requires authorization with granted `admin` role and adds the task to the list
Make sure to fill the var `issuer` with your own domain. This is the domain of your instance you can find it on the instance detail in the ZITADEL Cloud Customer Portal or in the ZITADEL Console. If authorization is required, the token must not be expired and the API has to be part of the audience (either client_id or project_id).
```go
package main
import ( For tests we will use a Personal Access Token.
"flag"
"log"
"net/http"
"time"
http_mw "github.com/zitadel/zitadel-go/v2/pkg/api/middleware/http"
"github.com/zitadel/zitadel-go/v2/pkg/client/middleware"
)
var (
issuer = flag.String("issuer", "", "issuer of your ZITADEL instance (in the form: https://<instance>.zitadel.cloud or https://<yourdomain>)")
)
func main() {
flag.Parse()
introspection, err := http_mw.NewIntrospectionInterceptor(*issuer, middleware.OSKeyPath())
if err != nil {
log.Fatal(err)
}
router := http.NewServeMux()
router.HandleFunc("/public", writeOK)
router.HandleFunc("/protected", introspection.HandlerFunc(writeOK))
lis := "127.0.0.1:5001"
log.Fatal(http.ListenAndServe(lis, router))
}
func writeOK(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK " + time.Now().String()))
}
```go reference
https://github.com/zitadel/zitadel-go/blob/next/example/api/http/main.go
``` ```
#### Key JSON You will need to provide some values for the program to run:
- `domain`: Your ZITADEL instance domain, e.g. https://my-domain.zitadel.cloud
- `key`: The path to the downloaded key.json
- `port`: The port on which the API will be accessible, default it 8089
To provide the key JSON to the SDK, simply set an environment variable `ZITADEL_KEY_PATH` with the path to the JSON as value. ## Test API
```bash
export ZITADEL_KEY_PATH=/Users/test/apikey.json
```
For development purposes you should be able to set this in your IDE.
If you're not able to set it via environment variable, you can also exchange the `middleware.OSKeyPath()` and pass it directly:
```go
introspection, err := http_mw.NewIntrospectionInterceptor(
client.Issuer,
"/Users/test/apikey.json",
)
```
### Test API
After you have configured everything correctly, you can simply start the example by: After you have configured everything correctly, you can simply start the example by:
```bash ```bash
go run main.go go run main.go --domain <your domain> --key <path>
``` ```
You can now call the API by browser or curl. Try the public endpoint first: This could look like:
```bash ```bash
curl -i localhost:5001/public go run main.go --domain https://my-domain.zitadel.cloud --key ./api.json
```
After you get a successful log:
```
2023/12/04 10:27:42 INFO server listening, press ctrl+c to stop addr=http://localhost:8089
```
### Public endpoint
Now you can call the API by browser or curl. Try the healthz endpoint first:
```bash
curl -i http://localhost:8089/api/healthz
``` ```
it should return something like: it should return something like:
``` ```
HTTP/1.1 200 OK HTTP/1.1 200 OK
Date: Tue, 24 Aug 2021 11:11:17 GMT Content-Type: application/json
Content-Length: 59 Date: Mon, 04 Dec 2023 09:29:38 GMT
Content-Type: text/plain; charset=utf-8 Content-Length: 4
OK 2021-08-24 13:11:17.135719 +0200 CEST m=+30704.913892168 "OK"
``` ```
and the protected: ### Task list
and the task list endpoint:
```bash ```bash
curl -i localhost:5001/protected curl -i http://localhost:8089/api/tasks
``` ```
it will return: it will return:
``` ```
HTTP/1.1 401 Unauthorized HTTP/1.1 401 Unauthorized
Content-Type: application/json Content-Type: text/plain; charset=utf-8
Date: Tue, 24 Aug 2021 11:13:10 GMT X-Content-Type-Options: nosniff
Content-Length: 21 Date: Mon, 04 Dec 2023 09:41:54 GMT
Content-Length: 44
"auth header missing" unauthorized: authorization header is empty
``` ```
Get a valid access_token for the API. You can achieve this by login into an application of the same project or Get a valid access_token for the API. You can either achieve this by getting an access token with the project_id in the audience
by explicitly requesting the project_id for the audience by scope `urn:zitadel:iam:org:project:id:{projectid}:aud`. or use a PAT of a service account.
If you provide a valid Bearer Token: If you provide a valid Bearer Token:
```bash ```bash
curl -i -H "Authorization: Bearer ${token}" localhost:5001/protected curl -i -H "Authorization: Bearer ${token}" http://localhost:8089/api/tasks
``` ```
it will return an OK response as well: it will return an empty list:
``` ```
HTTP/1.1 200 OK HTTP/1.1 200 OK
Date: Tue, 24 Aug 2021 11:13:33 GMT Content-Type: application/json
Content-Length: 59 Date: Mon, 04 Dec 2023 09:49:06 GMT
Content-Type: text/plain; charset=utf-8 Content-Length: 2
OK 2021-08-24 13:13:33.131943 +0200 CEST m=+30840.911149251 {}
```
### Try to add a new task
Let's see what happens if you call the AddTask endpoint:
```bash
curl -i -H "Authorization: Bearer ${token}" http://localhost:8089/api/add-task
```
it will complain about the missing `admin` role:
```
HTTP/1.1 403 Forbidden
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Mon, 04 Dec 2023 09:52:00 GMT
Content-Length: 50
permission denied: missing required role: `admin`
```
### Add admin role
So let's create the role and grant it to the user. To do so, go to your project in ZITADEL Console
and create the role by selecting `Roles` in the navigation and then clicking on the `New Role` button.
Finally, create the role as shown below:
![Create project role in console](/img/go/api-project-role.png)
After you have created the role, let's grant it the user, who requested the tasks.
Click on `Authorization` in the navigation and create a new one by selecting the user and the `admin` role.
After successful creation, it should look like:
![Created authorization in console](/img/go/api-project-auth.png)
So you should now be able to add a new task:
```bash
curl -i -H "Authorization: Bearer ${token}" http://localhost:8089/api/add-task --data "task=My new task"
```
which will report back the successful addition:
```
HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 04 Dec 2023 10:06:29 GMT
Content-Length: 26
"task `My new task` added"
```
Let's now retrieve the task list again:
```bash
curl -i -H "Authorization: Bearer ${token}" http://localhost:8089/api/tasks
```
As you can see your new task ist listed. And since you're an `admin` now, you will always get an additional `create a new task on /api/add-task`:
```
HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 04 Dec 2023 10:08:38 GMT
Content-Length: 62
{"tasks":["My new task","create a new task on /api/add-task"]}
``` ```

BIN
docs/static/img/go/api-create-auth.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
docs/static/img/go/api-create-key.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/static/img/go/api-create.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
docs/static/img/go/api-project-auth.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/static/img/go/api-project-role.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB