mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
generate and validate authorization message
This commit is contained in:
parent
12dfca0da3
commit
6412bd4df1
@ -4447,6 +4447,7 @@ components:
|
|||||||
- keyType
|
- keyType
|
||||||
- publicKey
|
- publicKey
|
||||||
- signature
|
- signature
|
||||||
|
- signatureType
|
||||||
properties:
|
properties:
|
||||||
messageType:
|
messageType:
|
||||||
type: string
|
type: string
|
||||||
@ -4463,6 +4464,9 @@ components:
|
|||||||
signature:
|
signature:
|
||||||
type: string
|
type: string
|
||||||
format: base64 encoding of message signature
|
format: base64 encoding of message signature
|
||||||
|
signatureType:
|
||||||
|
type: string
|
||||||
|
enum: [PKCS1v15, PSS]
|
||||||
|
|
||||||
|
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
|
@ -36,13 +36,8 @@ func AddAccount(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// compute key fingerprint
|
// compute key fingerprint
|
||||||
msg := []byte(publicPem)
|
msg := []byte(publicPem)
|
||||||
hash := sha256.New()
|
hash := sha256.Sum256(msg)
|
||||||
if _, err = hash.Write(msg); err != nil {
|
fingerprint := hex.EncodeToString(hash[:])
|
||||||
LogMsg("failed to fingerprint key")
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fingerprint := hex.EncodeToString(hash.Sum(nil))
|
|
||||||
|
|
||||||
// create new account
|
// create new account
|
||||||
account := store.Account{
|
account := store.Account{
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package databag
|
package databag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/rsa"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/base64"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Authorize(w http.ResponseWriter, r *http.Request) {
|
func Authorize(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
account, res := BearerAppToken(r);
|
account, res := BearerAppToken(r, true);
|
||||||
if res != nil {
|
if res != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
@ -19,13 +25,22 @@ func Authorize(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// extract token from body
|
// extract token from body
|
||||||
var token string
|
var token string
|
||||||
if ParseRequest(r, w, &token) != nil {
|
err := ParseRequest(r, w, &token)
|
||||||
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest);
|
w.WriteHeader(http.StatusBadRequest);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// load details to sign data
|
// load details to sign data
|
||||||
|
if account.AccountDetail.KeyType != "RSA4096" {
|
||||||
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
privateKey, res := ParseRsaPrivateKeyFromPemStr(account.AccountDetail.PrivateKey);
|
||||||
|
if res != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// generate message
|
// generate message
|
||||||
auth := Authenticate{
|
auth := Authenticate{
|
||||||
@ -33,8 +48,27 @@ func Authorize(w http.ResponseWriter, r *http.Request) {
|
|||||||
Token: token,
|
Token: token,
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
PrintMsg(auth);
|
var data []byte
|
||||||
|
data, err = json.Marshal(auth);
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hash := sha256.Sum256(data);
|
||||||
|
var signature []byte
|
||||||
|
signature, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := DataMessage{
|
||||||
|
MessageType: "authenticate",
|
||||||
|
Message: base64.StdEncoding.EncodeToString([]byte(data)),
|
||||||
|
KeyType: account.AccountDetail.KeyType,
|
||||||
|
PublicKey: base64.StdEncoding.EncodeToString([]byte(account.AccountDetail.PublicKey)),
|
||||||
|
Signature: base64.StdEncoding.EncodeToString(signature),
|
||||||
|
SignatureType: "PKCS1v15",
|
||||||
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
WriteResponse(w, msg)
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ func BearerAccountToken(r *http.Request) (store.AccountToken, error) {
|
|||||||
return accountToken, err
|
return accountToken, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func BearerAppToken(r *http.Request) (store.Account, error) {
|
func BearerAppToken(r *http.Request, detail bool) (store.Account, error) {
|
||||||
|
|
||||||
// parse bearer authentication
|
// parse bearer authentication
|
||||||
auth := r.Header.Get("Authorization")
|
auth := r.Header.Get("Authorization")
|
||||||
@ -87,8 +87,16 @@ func BearerAppToken(r *http.Request) (store.Account, error) {
|
|||||||
|
|
||||||
// find token record
|
// find token record
|
||||||
var app store.App
|
var app store.App
|
||||||
err := store.DB.Preload("Account").Where("token = ?", token).First(&app).Error
|
if detail {
|
||||||
return app.Account, err
|
if store.DB.Preload("Account.AccountDetail").Where("token = ?", token).First(&app).Error != nil {
|
||||||
|
return app.Account, errors.New("failed to load account");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if store.DB.Preload("Account").Where("token = ?", token).First(&app).Error != nil {
|
||||||
|
return app.Account, errors.New("failed to load account");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return app.Account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func BasicCredentials(r *http.Request) (string, []byte, error) {
|
func BasicCredentials(r *http.Request) (string, []byte, error) {
|
||||||
|
@ -132,6 +132,7 @@ type DataMessage struct {
|
|||||||
KeyType string `json:"keyType"`
|
KeyType string `json:"keyType"`
|
||||||
PublicKey string `json:"publicKey"`
|
PublicKey string `json:"publicKey"`
|
||||||
Signature string `json:"signature"`
|
Signature string `json:"signature"`
|
||||||
|
SignatureType string `json:"signatureType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Dialogue struct {
|
type Dialogue struct {
|
||||||
|
@ -2,6 +2,13 @@ package databag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/base64"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto"
|
||||||
|
"time"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +40,27 @@ func TestAttachAccount(t *testing.T) {
|
|||||||
var message DataMessage
|
var message DataMessage
|
||||||
assert.NoError(t, ReadResponse(w, &message))
|
assert.NoError(t, ReadResponse(w, &message))
|
||||||
|
|
||||||
|
// validate message
|
||||||
|
assert.Equal(t, "RSA4096", message.KeyType)
|
||||||
|
assert.Equal(t, "PKCS1v15", message.SignatureType)
|
||||||
|
var data []byte
|
||||||
|
var hash [32]byte
|
||||||
|
data, _ = base64.StdEncoding.DecodeString(message.PublicKey)
|
||||||
|
hash = sha256.Sum256(data)
|
||||||
|
guid := hex.EncodeToString(hash[:])
|
||||||
|
publicKey, _ := ParseRsaPublicKeyFromPemStr(string(data))
|
||||||
|
signature, _ := base64.StdEncoding.DecodeString(message.Signature)
|
||||||
|
data, _ = base64.StdEncoding.DecodeString(message.Message)
|
||||||
|
hash = sha256.Sum256(data)
|
||||||
|
assert.NoError(t, rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature))
|
||||||
|
var auth Authenticate
|
||||||
|
assert.NoError(t, json.Unmarshal(data,&auth))
|
||||||
|
assert.Equal(t, "aabbccdd", auth.Token)
|
||||||
|
assert.Equal(t, guid, auth.Guid)
|
||||||
|
cur := time.Now().Unix()
|
||||||
|
assert.GreaterOrEqual(t, cur, auth.Timestamp)
|
||||||
|
assert.Less(t, cur - 60, auth.Timestamp)
|
||||||
|
|
||||||
// set profile
|
// set profile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user