...
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/coreos/go-oidc/v3/oidc"
13 "github.com/gin-gonic/gin"
14 "github.com/golang-jwt/jwt/v4"
15 "golang.org/x/oauth2"
16
17 "edge-infra.dev/pkg/edge/iam/log"
18 )
19
20 func (v *Verifier) scanBarcode(ctx *gin.Context) {
21 log := log.Get(ctx.Request.Context())
22
23
24 barcode := ctx.Query("barcode")
25 if barcode == "" {
26 log.Info("No barcode value found")
27 ctx.AbortWithStatus(http.StatusBadRequest)
28 return
29 }
30
31
32 data := url.Values{}
33 data.Set("client_id", v.ClientID)
34 data.Set("client_secret", v.ClientSecret)
35 data.Set("grant_type", "barcode")
36 data.Set("barcode", barcode)
37
38
39 res, err := http.Post(IssuerURL()+oauth2TokenPath, gin.MIMEPOSTForm, bytes.NewBufferString(data.Encode()))
40 if err != nil {
41 log.Info("failed to get token from barcode scan", "error", err)
42 err := ctx.AbortWithError(http.StatusInternalServerError, err)
43 if err != nil {
44 log.Error(err, "failed to abort with error")
45 }
46 return
47 }
48
49 defer res.Body.Close()
50
51 if res.StatusCode != http.StatusOK {
52 loginhint := res.Header.Get("WWW-Authenticate")
53 if loginhint == "" {
54 ctx.AbortWithStatus(res.StatusCode)
55 return
56 }
57
58 provider, err := oidc.NewProvider(oidc.InsecureIssuerURLContext(ctx, Issuer()), IssuerURL())
59 if err != nil {
60 err := ctx.AbortWithError(http.StatusInternalServerError, err)
61 if err != nil {
62 log.Error(err, "failed to abort with error")
63 }
64 return
65 }
66
67 config := oauth2.Config{
68 ClientID: v.ClientID,
69 ClientSecret: v.ClientSecret,
70 RedirectURL: v.ClientURL + verifyCallbackPath,
71 Endpoint: provider.Endpoint(),
72 Scopes: []string{oidc.ScopeOpenID, oidc.ScopeOfflineAccess, "profile"},
73 }
74
75
76 authCodeURL := config.AuthCodeURL("332b7b6ue34ds", oauth2.SetAuthURLParam("login_hint", loginhint[6:]))
77 ctx.AbortWithStatusJSON(res.StatusCode, authCodeURL)
78 return
79 }
80
81
82 body, err := io.ReadAll(res.Body)
83 if err != nil {
84 log.Error(err, "Error reading response")
85 return
86 }
87
88
89 var tokenRes TokenResponse
90 err = json.Unmarshal(body, &tokenRes)
91 if err != nil {
92 log.Error(err, "Error unmarshaling response")
93 return
94 }
95
96
97 jwksURL := IssuerURL() + wellKnownJWKSPath
98 jwks, err := keyfunc.Get(jwksURL, keyfunc.Options{})
99 if err != nil {
100 log.Info("failed get jwks", "error", err)
101 err := ctx.AbortWithError(http.StatusInternalServerError, err)
102 if err != nil {
103 log.Error(err, "failed to abort with error")
104 }
105 return
106 }
107
108
109 accessToken, err := jwt.Parse(tokenRes.AccessToken, jwks.Keyfunc)
110 if err != nil {
111 log.Info("failed to validate accesstoken", "error", err)
112 err := ctx.AbortWithError(http.StatusInternalServerError, err)
113 if err != nil {
114 log.Error(err, "failed to abort with error")
115 }
116 return
117 }
118
119 if accessToken.Valid {
120 ctx.AbortWithStatus(http.StatusOK)
121 return
122 }
123
124 ctx.AbortWithStatus(http.StatusUnauthorized)
125 }
126
View as plain text