/
basic.go
103 lines (80 loc) · 2.25 KB
/
basic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2020 Author: Ruslan Bikchentaev. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package auth
import (
"bytes"
"encoding/base64"
"regexp"
"github.com/pkg/errors"
"github.com/ruslanBik4/logs"
"github.com/valyala/fasthttp"
)
type fncNewTokenData func(ctx *fasthttp.RequestCtx, user, pass []byte) TokenData
type AuthBasic struct {
tokens Tokens
// maps basic string to tokens
mapBasicToTokens map[string]string
NewTokenData fncNewTokenData
}
func NewAuthBasic(tokens Tokens, fnc fncNewTokenData) *AuthBasic {
return &AuthBasic{tokens, make(map[string]string), fnc}
}
func (a *AuthBasic) Auth(ctx *fasthttp.RequestCtx) bool {
b := a.getBasic(ctx)
if len(b) > 0 {
token, ok := a.mapBasicToTokens[string(b)]
if ok {
data := a.tokens.GetToken(token)
if data != nil {
ctx.Response.Header.Set("token", token)
return true
}
}
u, p, ok := a.getUserPass(b)
if ok {
data := a.NewTokenData(ctx, u, p)
if data != nil {
token, err := a.tokens.NewToken(data)
if err == nil {
a.mapBasicToTokens[string(b)] = token
ctx.Response.Header.Set("token", token)
return true
}
logs.ErrorLog(errors.Wrap(err, ""))
}
}
logs.DebugLog("%s:'%s'", string(p), string(u))
}
ctx.Response.Header.Set("WWW-Authenticate", `Basic realm="User Visible Realm", charset="UTF-8"`)
return false
}
func (a *AuthBasic) AdminAuth(ctx *fasthttp.RequestCtx) bool {
return false
}
func (a *AuthBasic) String() string {
return "Basic access authentication"
}
var regBasic = regexp.MustCompile(`Basic\s+(\S+)`)
func (a *AuthBasic) getBasic(ctx *fasthttp.RequestCtx) []byte {
b := regBasic.FindSubmatch(ctx.Request.Header.Peek("Authorization"))
if len(b) == 0 {
return nil
}
return b[1]
}
func (a *AuthBasic) getUserPass(b []byte) (user []byte, pass []byte, ok bool) {
enc := base64.StdEncoding
dst := make([]byte, enc.DecodedLen(len(b)))
n, err := enc.Decode(dst, b)
if err != nil {
logs.ErrorLog(err, "Decode "+string(b))
return nil, nil, false
}
pair := bytes.SplitN(dst[:n], []byte(":"), -1)
if len(pair) != 2 {
logs.DebugLog("'%s' <- '%s'", string(dst[:n]), string(b))
return nil, nil, false
}
return pair[0], pair[1], true
}