Skip to content

Commit

Permalink
feat: introspect access token
Browse files Browse the repository at this point in the history
  • Loading branch information
Salaton committed Jan 17, 2023
1 parent 8aa8858 commit 6cbc207
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 13 deletions.
74 changes: 74 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package authutils

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
Expand All @@ -10,6 +12,7 @@ import (
"time"

"github.com/go-playground/validator"
"moul.io/http2curl"
)

// Client bundles data needed by methods in order to interact with the casdoor API
Expand Down Expand Up @@ -101,3 +104,74 @@ func (c *Client) Authenticate() error {

return nil
}

// VerifyAccessToken is used to introspect a token to determine the active state of the
// OAuth 2.0 access token and to determine meta-information about this token.
func (c *Client) VerifyAccessToken(ctx context.Context, accessToken string) (*TokenIntrospectionResponse, error) {
if accessToken == "" {
return nil, fmt.Errorf("unable to get access token from the input")
}

introspectionURL := fmt.Sprintf("%s/v1/app/introspect/", c.configurations.AuthServerEndpoint)
payload := TokenIntrospectionPayload{
TokenType: "access_token",
Token: accessToken,
}

response, err := c.makeRequest(ctx, http.MethodPost, introspectionURL, payload, "application/json")
if err != nil {
return nil, err
}

resp, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}

var introspectionResponse *TokenIntrospectionResponse
err = json.Unmarshal(resp, &introspectionResponse)
if err != nil {
return nil, err
}

if !introspectionResponse.IsValid {
return nil, fmt.Errorf("the supplied access token is invalid")
}

return introspectionResponse, nil
}

// makeRequest is a helper function for making http requests
func (c *Client) makeRequest(
ctx context.Context,
method string,
path string,
body interface{},
contentType string,
) (*http.Response, error) {
client := http.Client{}

encoded, err := json.Marshal(body)
if err != nil {
return nil, err
}

payload := bytes.NewBuffer(encoded)
req, err := http.NewRequestWithContext(ctx, method, path, payload)
if err != nil {
return nil, err
}

req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", contentType)

command, _ := http2curl.GetCurlCommand(req)
fmt.Println(command)

response, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("an error occurred while sending a HTTP request: %w", err)
}

return response, nil
}
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ module github.com/savannahghi/authutils

go 1.18

require github.com/go-playground/validator v9.31.0+incompatible
require (
github.com/go-playground/validator v9.31.0+incompatible
moul.io/http2curl v1.0.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/smartystreets/goconvey v1.7.2 // indirect
github.com/stretchr/testify v1.7.0 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
Expand Down
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,34 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8=
moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
25 changes: 14 additions & 11 deletions models.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package authutils

import "time"

// LoginResponse defines the object returned when a user successfully logs in
type LoginResponse struct {
Scope string `json:"scope"`
Expand All @@ -26,17 +28,12 @@ type CasdoorErrorResponse struct {

// TokenIntrospectionResponse defines the JSON object returned by the CASDOOR service during token introspection
type TokenIntrospectionResponse struct {
Active bool `json:"active"`
ClientID string `json:"client_id"`
Username string `json:"username"`
TokenType string `json:"token_type"`
Exp int `json:"exp"`
Iat int `json:"iat"`
Nbf int `json:"nbf"`
Sub string `json:"sub"`
Aud []string `json:"aud"`
Iss string `json:"iss"`
Jti string `json:"jti"`
ClientID string `json:"client_id"`
Expires time.Time `json:"expires"`
IsValid bool `json:"is_valid"`
Scope string `json:"scope"`
Token string `json:"token"`
UserGUID string `json:"user_guid"`
}

// Response defines the JSON object returned by most casdoor APIs
Expand All @@ -48,3 +45,9 @@ type Response struct {
Data interface{} `json:"data"`
Data2 interface{} `json:"data2"`
}

// TokenIntrospectionPayload defines the json object passed when introspecting a token
type TokenIntrospectionPayload struct {
TokenType string `json:"token_type"`
Token string `json:"token"`
}
2 changes: 1 addition & 1 deletion utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ func GetLoggedInUserUID(ctx context.Context) (string, error) {
return "", fmt.Errorf("wrong auth token type, got %v", token)
}

return token.Sub, nil
return token.UserGUID, nil
}

0 comments on commit 6cbc207

Please sign in to comment.