/
providers.go
79 lines (67 loc) · 1.77 KB
/
providers.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
// Copyright (c) 2020, Arveto Ink. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
package public
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/json"
"encoding/pem"
"github.com/HuguesGuilleus/go-parsersa"
"net/http"
"time"
)
// The information about the providers,
type Provider struct {
PrivKey *rsa.PrivateKey
Pub []byte // the PEM public key encoded
}
// Create a new app. id is the the id of the this application in the provider.
// serv is the url of this provider.
func NewProvider(keyFile string) (*Provider, error) {
k, err := parsersa.GenPrivKey(keyFile, 2048)
if err != nil {
return nil, err
}
buff := &bytes.Buffer{}
pem.Encode(buff, &pem.Block{
Type: "BEGIN PUBLIC KEY",
Bytes: x509.MarshalPKCS1PublicKey(&k.PublicKey),
})
return &Provider{
PrivKey: k,
Pub: buff.Bytes(),
}, nil
}
func (p *Provider) PubHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/x-pem-file")
w.Write(p.Pub)
}
const (
// The header `{"alg": "RS256","typ": "JWT"}` already encoded + dot
jwtHead = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9."
// The duration of a day
day = 24 * time.Hour
)
// Create a JWT for the user u to a specific audience.
func (p *Provider) CreateJWT(u *UserInfo, audience string) (string, error) {
j, err := json.Marshal(jwtBody{
UserInfo: *u,
Audience: audience,
ExpirationTime: time.Now().Add(day).Unix(),
})
if err != nil {
return "", err
}
body := jwtHead + tob64(j)
hashed := sha256.Sum256([]byte(body))
sig, err := rsa.SignPKCS1v15(rand.Reader, p.PrivKey, crypto.SHA256, hashed[:])
if err != nil {
return "", err
}
return body + "." + tob64(sig), nil
}