...

Source file src/edge-infra.dev/pkg/edge/iam/verify/verifier_scan_barcode.go

Documentation: edge-infra.dev/pkg/edge/iam/verify

     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  	// Access the form data
    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  	// setting the http body in x-www-form-urlencoded form
    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  	// Make a POST request to the token endpoint
    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  		// removing the first 6 charcters as it has "login {login_hint}"
    76  		authCodeURL := config.AuthCodeURL("332b7b6ue34ds", oauth2.SetAuthURLParam("login_hint", loginhint[6:]))
    77  		ctx.AbortWithStatusJSON(res.StatusCode, authCodeURL)
    78  		return
    79  	}
    80  
    81  	// Read the response body of token endpoint
    82  	body, err := io.ReadAll(res.Body)
    83  	if err != nil {
    84  		log.Error(err, "Error reading response")
    85  		return
    86  	}
    87  
    88  	// Unmarshal the response JSON into a TokenResponse struct
    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  	// accessing jwks (will be used for parsing the JWT token)
    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  	// parse and validate the access token
   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