github.com/gramework/gramework@v1.8.1-0.20231027140105-82555c9057f5/context_Auth.go (about)

     1  // Copyright 2017-present Kirill Danshin and Gramework contributors
     2  // Copyright 2019-present Highload LTD (UK CN: 11893420)
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  
    11  package gramework
    12  
    13  import (
    14  	"bytes"
    15  	"encoding/base64"
    16  	"errors"
    17  )
    18  
    19  var (
    20  	authHeaderName = []byte("Authorization")
    21  	authSplitter   = []byte(":")
    22  	errInvalidAuth = errors.New("invalid auth request")
    23  )
    24  
    25  // GetPass lazy triggers parser and returns
    26  // password or an error. Error will be persistent
    27  // for current context
    28  //
    29  // Common typos: GetPassword
    30  func (a *Auth) GetPass() (string, error) {
    31  	// yep, we copying the code, but
    32  	// we get one instead of two jumps
    33  	if !a.parsed {
    34  		a.parse()
    35  	}
    36  
    37  	return a.pass, a.err
    38  }
    39  
    40  // GetLogin lazy triggers parser and returns
    41  // login or an error. Error will be persistent
    42  // for current context
    43  //
    44  // Common typos: GetUser, GetUsername
    45  func (a *Auth) GetLogin() (string, error) {
    46  	if !a.parsed {
    47  		a.parse()
    48  	}
    49  
    50  	return a.login, a.err
    51  }
    52  
    53  func (a *Auth) parse() {
    54  	if a.err != nil {
    55  		return // parsing already failed
    56  	}
    57  	auth := a.ctx.Request.Header.PeekBytes(authHeaderName)
    58  	if len(auth) < 7 {
    59  		a.err = errInvalidAuth
    60  		return
    61  	}
    62  	decoded, err := base64.StdEncoding.DecodeString(BytesToString(auth[6:]))
    63  	if err != nil {
    64  		a.err = err
    65  		return
    66  	}
    67  
    68  	splitted := bytes.Split(decoded, authSplitter)
    69  
    70  	if len(splitted) != 2 {
    71  		a.err = errInvalidAuth
    72  		return
    73  	}
    74  
    75  	a.login, a.pass = string(splitted[0]), string(splitted[1])
    76  }
    77  
    78  // Auth returns struct for simple basic auth handling
    79  //
    80  // useful to develop e.g. stage environment login,
    81  // where high security is not required
    82  func (ctx *Context) Auth() *Auth {
    83  	if ctx.auth == nil {
    84  		ctx.auth = &Auth{
    85  			ctx: ctx,
    86  		}
    87  	}
    88  	return ctx.auth
    89  }