Skip to content

Commit

Permalink
Merge pull request #60 from silinternational/develop
Browse files Browse the repository at this point in the history
Release v2.1.1 - Cleanup IAM policy, update webauthn Go library
  • Loading branch information
forevermatt authored Aug 21, 2023
2 parents 7b8e066 + a291459 commit 0bbfb3c
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 1,175 deletions.
4 changes: 2 additions & 2 deletions fixtures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package mfa
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/duo-labs/webauthn/webauthn"
"github.com/go-webauthn/webauthn/webauthn"
)

type baseTestConfig struct {
Expand All @@ -14,7 +14,6 @@ type baseTestConfig struct {
}

func getDBConfig(ms *MfaSuite) baseTestConfig {

awsConfig := testAwsConfig()
envCfg := testEnvConfig(awsConfig)
localStorage, err := NewStorage(&awsConfig)
Expand All @@ -24,6 +23,7 @@ func getDBConfig(ms *MfaSuite) baseTestConfig {
RPDisplayName: "TestRPName", // Display Name for your site
RPID: "111.11.11.11", // Generally the FQDN for your site
Debug: true,
RPOrigins: []string{testRpOrigin},
})

ms.NoError(err, "failed creating new webAuthnClient for test")
Expand Down
15 changes: 9 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,29 @@ go 1.18
require (
github.com/aws/aws-lambda-go v1.37.0
github.com/aws/aws-sdk-go v1.44.201
github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec
github.com/fxamacker/cbor/v2 v2.4.0
github.com/go-webauthn/webauthn v0.8.6
github.com/gorilla/mux v1.8.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/pkg/errors v0.9.1
github.com/satori/go.uuid v1.2.0
github.com/stretchr/testify v1.8.1
golang.org/x/crypto v0.6.0
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.11.0
)

require (
github.com/cloudflare/cfssl v1.6.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang-jwt/jwt/v4 v4.4.3 // indirect
github.com/google/certificate-transparency-go v1.1.4 // indirect
github.com/go-webauthn/x v0.1.4 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/google/go-tpm v0.9.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/sys v0.10.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
1,140 changes: 14 additions & 1,126 deletions go.sum

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions terraform/lambda-role-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
"dynamodb:GetItem"
],
"Resource": [
"arn:aws:dynamodb:*:${aws_account}:table/${api_key_table}",
"arn:aws:dynamodb:*:${aws_account}:table/${api_key_table}_global"
"arn:aws:dynamodb:*:${aws_account}:table/${api_key_table}"
],
"Effect": "Allow"
},
Expand All @@ -51,8 +50,7 @@
"dynamodb:DeleteItem"
],
"Resource": [
"arn:aws:dynamodb:*:${aws_account}:table/${webauthn_table}",
"arn:aws:dynamodb:*:${aws_account}:table/${webauthn_table}_global"
"arn:aws:dynamodb:*:${aws_account}:table/${webauthn_table}"
],
"Effect": "Allow"
}
Expand Down
32 changes: 17 additions & 15 deletions u2fsimulator/u2fsimulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (
"strings"
"time"

"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/protocol/webauthncbor"
"github.com/duo-labs/webauthn/protocol/webauthncose"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/protocol/webauthncbor"
"github.com/go-webauthn/webauthn/protocol/webauthncose"
)

const (
Expand Down Expand Up @@ -120,7 +120,7 @@ func getPrivateKey() *ecdsa.PrivateKey {
}

// GetAuthDataAndPrivateKey return the authentication data as a string and as a byte slice
// and also returns the private key
// and also returns the private key
func GetAuthDataAndPrivateKey(rpID, keyHandle string) (authDataStr string, authData []byte, privateKey *ecdsa.PrivateKey) {
// Add in the RP ID Hash (32 bytes)
RPIDHash := sha256.Sum256([]byte(rpID))
Expand Down Expand Up @@ -197,7 +197,6 @@ func getCertBytes(privateKey *ecdsa.PrivateKey, serialNumber *big.Int, certReade
// GetASN1Signature signs a hash (which should be the result of hashing a larger message)
// using the private key.
func GetASN1Signature(notRandom io.Reader, privateKey *ecdsa.PrivateKey, sha256Digest []byte) (DsaSignature, []byte) {

r, s, err := ecdsa.Sign(notRandom, privateKey, sha256Digest[:])
if err != nil {
panic("error generating signature: " + err.Error())
Expand All @@ -214,11 +213,9 @@ func GetASN1Signature(notRandom io.Reader, privateKey *ecdsa.PrivateKey, sha256D
}

// getSignatureForAttObject starts with byte(0) and appends the sha256 sum of the rpOrigin and of the clientData
// and then appends the keyHandle and an elliptic Marshalled version of the public key
// It does a sha256 sum of that and creates a dsa signature of it with the private key and without using any
// randomizing
// and then appends the keyHandle and an elliptic Marshalled version of the public key. It does a sha256 sum of
// that and creates a dsa signature of it with the private key and without using any randomizing.
func getSignatureForAttObject(notRandom io.Reader, clientData []byte, keyHandle string, privateKey *ecdsa.PrivateKey, rpOrigin string) []byte {

appParam := sha256.Sum256([]byte(rpOrigin))
challenge := sha256.Sum256(clientData)

Expand Down Expand Up @@ -284,17 +281,22 @@ type U2fRegistrationResponse struct {
}

// U2fRegistration is intended to assist with automated testing by
// returning to an api server something similar to what a client
// would return following a registration ceremony with a U2F key
// returning to an api server something similar to what a client
// would return following a registration ceremony with a U2F key
//
// It expects a POST call with the following elements in the body/form
//
// "challenge"
// "keyHandle" (optional)
// (Although the api server wouldn't normally deal with a challenge and keyHandle,
// including them here allows for more predictability with the test results.)
//
// (Although the api server wouldn't normally deal with a challenge and keyHandle,
// including them here allows for more predictability with the test results.)
//
// It also expects the following headers to be set on the request
//
// "x-mfa-RPID"
// "x-mfa-RPOrigin"
// "x-mfa-UserUUID"
// "x-mfa-RPOrigin"
// "x-mfa-UserUUID"
func U2fRegistration(w http.ResponseWriter, r *http.Request) {
reqBody, err := io.ReadAll(r.Body)
if err != nil {
Expand Down
20 changes: 9 additions & 11 deletions user.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"log"
"net/http"

cbor "github.com/fxamacker/cbor/v2"
"github.com/fxamacker/cbor/v2"
"github.com/pkg/errors"

"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/protocol/webauthncose"
"github.com/duo-labs/webauthn/webauthn"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/protocol/webauthncose"
"github.com/go-webauthn/webauthn/webauthn"
)

const (
Expand Down Expand Up @@ -133,12 +133,10 @@ func (u *DynamoUser) saveNewCredential(credential webauthn.Credential) error {
return u.encryptAndStoreCredentials()
}

// DeleteCredential expects a hashed-encoded credential id.
// It finds a matching credential for that user and saves the user
// without that credential included.
// Alternatively, if the given credential id indicates that a legacy U2F key should be removed
// (e.g. by matching the string "u2f")
// then that user is saved with all of its legacy u2f fields blanked out.
// DeleteCredential expects a hashed-encoded credential id. It finds a matching credential for that user and saves the
// user without that credential included. Alternatively, if the given credential id indicates that a legacy U2F key
// should be removed (e.g. by matching the string "u2f") then that user is saved with all of its legacy u2f fields
// blanked out.
func (u *DynamoUser) DeleteCredential(credIDHash string) (int, error) {
// load to be sure working with the latest data
err := u.Load()
Expand Down Expand Up @@ -371,7 +369,7 @@ func (u *DynamoUser) FinishLogin(r *http.Request) (*webauthn.Credential, error)
}

// there is an issue with URLEncodeBase64.UnmarshalJSON and null values
// see https://github.com/duo-labs/webauthn/issues/69
// see https://github.com/go-webauthn/webauthn/issues/69
// null byte sequence is []byte{158,233,101}
if isNullByteSlice(parsedResponse.Response.UserHandle) {
parsedResponse.Response.UserHandle = nil
Expand Down
4 changes: 2 additions & 2 deletions webauthn.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"net/http"
"strings"

"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/webauthn"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/gorilla/mux"
uuid "github.com/satori/go.uuid"
)
Expand Down
16 changes: 7 additions & 9 deletions webauthn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/webauthn"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/gorilla/mux"
"github.com/stretchr/testify/require"

Expand All @@ -35,7 +35,7 @@ const (
testRpId = "dKbqkhPJnC90siSSsyDPQCYqlMGpUKA5fyklC2CEHvA"

AssertionTypeFido = "fido-u2f"
testRpOrigin = "localhost"
testRpOrigin = "https://example.com"
)

func getTestAssertionResponse(credID, authData, clientData, attestationObject string) []byte {
Expand All @@ -52,7 +52,6 @@ func getTestAssertionResponse(credID, authData, clientData, attestationObject st
}

func getTestAssertionRequest(credID1, authData1, clientData1, attestObject1 string, user *DynamoUser) *http.Request {

assertResp := getTestAssertionResponse(credID1, authData1, clientData1, attestObject1)

body := ioutil.NopCloser(bytes.NewReader(assertResp))
Expand Down Expand Up @@ -138,6 +137,7 @@ func (ms *MfaSuite) Test_BeginRegistration() {
RPDisplayName: "TestRPName", // Display Name for your site
RPID: "111.11.11.11", // Generally the FQDN for your site
Debug: true,
RPOrigins: []string{testRpOrigin},
})

ms.NoError(err, "failed creating new webAuthnClient for test")
Expand Down Expand Up @@ -429,6 +429,7 @@ func (ms *MfaSuite) Test_BeginLogin() {
RPDisplayName: "TestRPName", // Display Name for your site
RPID: "111.11.11.11", // Generally the FQDN for your site
Debug: true,
RPOrigins: []string{testRpOrigin},
})

ms.NoError(err, "failed creating new webAuthnClient for test")
Expand Down Expand Up @@ -629,7 +630,7 @@ func (ms *MfaSuite) Test_FinishLogin() {

signature1 := GenerateAuthenticationSig(authDataBytes1, cdBytes, privateKey1)

var assertionResponse1 = `{
assertionResponse1 := `{
"id":"` + credIDEncoded1 + `",
"rawId":"` + credIDEncoded1 + `",
"type":"public-key",
Expand All @@ -651,7 +652,7 @@ func (ms *MfaSuite) Test_FinishLogin() {

signature2 := GenerateAuthenticationSig(authDataBytes2, cdBytes, privateKey1)

var assertionResponse2 = `{
assertionResponse2 := `{
"id":"` + credIDEncoded2 + `",
"rawId":"` + credIDEncoded2 + `",
"type":"public-key",
Expand Down Expand Up @@ -768,7 +769,6 @@ func Test_GetPublicKeyAsBytes(t *testing.T) {
want := []byte{4, 6, 214, 26, 66, 24, 173, 50, 249, 174, 188, 167, 158, 81, 153, 174, 135, 222, 147, 153, 116, 209, 27, 16, 127, 233, 183, 236, 149, 105, 147, 84, 94, 138, 214, 31, 142, 253, 63, 17, 232, 200, 228, 33, 96, 172, 95, 227, 235, 203, 196, 73, 134, 227, 177, 108, 60, 40, 190, 118, 9, 6, 237, 18, 103}

assert.Equal(want, got, "incorrect public Key")

}

func Router() *mux.Router {
Expand Down Expand Up @@ -802,7 +802,6 @@ func testAuthnMiddleware(next http.Handler) http.Handler {
}

func (ms *MfaSuite) Test_DeleteCredential() {

baseConfigs := getDBConfig(ms)

users := getTestWebauthnUsers(ms, baseConfigs)
Expand Down Expand Up @@ -876,7 +875,6 @@ func (ms *MfaSuite) Test_DeleteCredential() {
}
for _, tt := range tests {
ms.T().Run(tt.name, func(t *testing.T) {

request, _ := http.NewRequest("DELETE", fmt.Sprintf("/webauthn/credential/%s", tt.credID), nil)

request.Header.Set("x-mfa-apikey", tt.user.ApiKeyValue)
Expand Down

0 comments on commit 0bbfb3c

Please sign in to comment.