...
1 package verify
2
3 import (
4 "bytes"
5 "encoding/json"
6 "io"
7
8 http "net/http"
9 "net/url"
10
11 "github.com/MicahParks/keyfunc"
12 "github.com/gin-gonic/gin"
13 "github.com/golang-jwt/jwt/v4"
14
15 "edge-infra.dev/pkg/edge/iam/log"
16 "edge-infra.dev/pkg/edge/iam/util"
17 "edge-infra.dev/pkg/edge/iam/verify/templates"
18 )
19
20 const (
21 oauth2TokenPath = "/oauth2/token"
22 wellKnownJWKSPath = "/.well-known/jwks.json"
23 verifyCallbackPath = "/verify/callback"
24 )
25
26 type TokenResponse struct {
27 AccessToken string `json:"access_token"`
28 TokenType string `json:"token_type"`
29 ExpiresIn int `json:"expires_in"`
30 Scope string `json:"scope"`
31 }
32
33 func (v *Verifier) client(ctx *gin.Context) {
34 log := log.Get(ctx.Request.Context())
35
36 result := &Result{
37 Name: "verify client result",
38 Pass: true,
39 }
40
41
42 jwksURL := IssuerURL() + wellKnownJWKSPath
43 jwks, err := keyfunc.Get(jwksURL, keyfunc.Options{})
44 if err != nil {
45 step := Step{Name: "load jwks", Pass: false}
46 writeResult(ctx, templates.Callback, result, step)
47 return
48 }
49
50
51 data := url.Values{}
52 data.Set("client_id", v.ClientID)
53 data.Set("client_secret", v.ClientSecret)
54 data.Set("grant_type", "client_credentials")
55
56
57 res, err := http.Post(IssuerURL()+oauth2TokenPath, "application/x-www-form-urlencoded", bytes.NewBufferString(data.Encode()))
58 if err != nil {
59 step := Step{Name: "make request to token endpoint", Pass: false}
60 writeResult(ctx, templates.Callback, result, step)
61 return
62 }
63
64 defer res.Body.Close()
65
66
67 body, err := io.ReadAll(res.Body)
68 if err != nil {
69 log.Error(err, "Error reading response")
70 return
71 }
72
73
74 var tokenRes TokenResponse
75 err = json.Unmarshal(body, &tokenRes)
76 if err != nil {
77 log.Error(err, "Error unmarshaling response")
78 return
79 }
80
81
82 accessToken, _ := jwt.Parse(tokenRes.AccessToken, jwks.Keyfunc)
83
84 rolesOk := false
85 if accessToken.Valid {
86
87 claims, _ := accessToken.Claims.(jwt.MapClaims)
88 serialisedRls, _ := claims["rls"].(string)
89 roles, _ := util.Deserialize(serialisedRls)
90
91
92 for _, role := range roles {
93 if role == "SELLING_EXECUTE" {
94 rolesOk = true
95 break
96 }
97 }
98 }
99
100 steps := make([]Step, 0)
101 steps = append(steps,
102 Step{Name: "valid access token", Pass: accessToken.Valid},
103 Step{Name: "roles include SELLING_EXECUTE", Pass: rolesOk},
104 )
105
106 writeResult(ctx, templates.Client, result, steps...)
107 }
108
View as plain text