Skip to content

Commit

Permalink
Moved the RSA keys into a keys folder. Updated the key generator to a…
Browse files Browse the repository at this point in the history
…dd them to the keys folder.

Updated .gitignore to ignore the keys folder and the .vscode folder too.
Tidied up the go.mod file.
Updated the types file to make all environment variable keys as variables.
Updated the types to also start creating the UserDocument type for use with JWTs
Updated main to use the new env variable.
Made new function to read the RSA public/private keys and set the string representations as environment variables.
Made new function to get RSA key representations for use with JWTs.
Added new web route for the public RSA key (for verification)
Updated the login post route to return a JWT
Removed the time & remoteAddress uniqueness values from the index for authNonces collection.
Added new removeUsedNonce function to remove nonces after use.
Used removeUsedNonce function immediately after checking the nonce after attempting to login
Implemented JWT generation in GetUserByUsername
  • Loading branch information
Mathew Thompson authored and Mathew Thompson committed Jul 3, 2021
1 parent b2c1456 commit 1456cb0
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 66 deletions.
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ fileRenamerCli
testFiles
.DS_Store

#RSA / JWT Key Files
jwtRS256.key
jwtRS256.key.pub
# RSA / JWT Key Files
keys/

# IDE stuff
.vscode
9 changes: 5 additions & 4 deletions gen-rsa-key.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
echo "Don't Add a passphrase"
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
cat jwtRS256.key
cat jwtRS256.key.pub
mkdir keys
ssh-keygen -t rsa -b 4096 -m PEM -f ./keys/jwtRS256.key
openssl rsa -in ./keys/jwtRS256.key -pubout -outform PEM -out ./keys/jwtRS256.key.pub
cat ./keys/jwtRS256.key
cat ./keys/jwtRS256.key.pub
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ go 1.16
require (
github.com/gin-gonic/gin v1.7.2
github.com/go-playground/validator/v10 v10.6.1 // indirect
github.com/gofrs/uuid v4.0.0+incompatible
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
github.com/golang-jwt/jwt v3.2.1+incompatible
github.com/golang/protobuf v1.5.2 // indirect
github.com/joho/godotenv v1.3.0
github.com/json-iterator/go v1.1.11 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
Expand Down
113 changes: 76 additions & 37 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"time"

"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"github.com/joho/godotenv"

"go.mongodb.org/mongo-driver/mongo"
Expand All @@ -33,89 +32,125 @@ func loadAndCheckEnvVariables() {
log.Fatal("Error loading .env file: ", err)
}

mongoDbUrl := os.Getenv("MONGO_DB_URL")
mongoDbUrl := os.Getenv(MONGO_DB_URL)
if len(mongoDbUrl) == 0 {
log.Fatal("MONGO_DB_URL environment variable is required")
}

mongoDbUser := os.Getenv("MONGO_DB_USERNAME")
mongoDbUser := os.Getenv(MONGO_DB_USERNAME)
if len(mongoDbUser) == 0 {
log.Fatal("MONGO_DB_USERNAME environment variable is required")
}

mongoDbPass := os.Getenv("MONGO_DB_PASSWORD")
mongoDbPass := os.Getenv(MONGO_DB_PASSWORD)
if len(mongoDbPass) == 0 {
log.Fatal("MONGO_DB_PASSWORD environment variable is required")
}

hashSecret := os.Getenv("HASH_SECRET")
openRSAErr := openAndSetRSAKeys()

if len(hashSecret) == 0 {
u2, err := uuid.NewV4()
if err != nil {
log.Fatalf("failed to generate UUID: %v", err)
}
if openRSAErr != nil {
msg := fmt.Sprintln("error opening RSA keys.", openRSAErr)
log.Fatal(msg)
}

checkRSAErr := checkRSAKeys()
if checkRSAErr != nil {
msg := fmt.Sprintln("cannot read RSA keys", checkRSAErr)
log.Fatal(msg)
}
}

func openAndSetRSAKeys() error {
privateKeyBytes, privateKeyBytesErr := os.ReadFile("./keys/jwtRS256.key")
if privateKeyBytesErr != nil {
return errors.New("private key does not exist or cannot be read. Run gen-rsa-key.sh to generate a key pair")
}

fmt.Println("New UUID: ", u2)
os.Setenv("HASH_SECRET", u2.String())
publicKeyBytes, publicKeyBytesErr := os.ReadFile("./keys/jwtRS256.key.pub")
if publicKeyBytesErr != nil {
return errors.New("public key does not exist or cannot be read. Run gen-rsa-key.sh to generate a key pair")
}

openJwtKeys()
os.Setenv(RSA_PRIVATE_KEY, string(privateKeyBytes))
os.Setenv(RSA_PUBLIC_KEY, string(publicKeyBytes))

return nil
}

func openJwtKeys() (*rsa.PrivateKey, *rsa.PublicKey, error) {
func GetRSAPrivateKey() (*rsa.PrivateKey, error) {
var privateKey *rsa.PrivateKey
var publicKey *rsa.PublicKey

privateKeyBytes, privateKeyBytesErr := os.ReadFile("jwtRS256.key")
if privateKeyBytesErr != nil {
return privateKey, publicKey, errors.New("private key does not exist or cannot be read. Run gen-rsa-key.sh to generate a key pair")
}
privateKeyStr := os.Getenv(RSA_PRIVATE_KEY)

privateKeyBytes := []byte(privateKeyStr)

privateKeyBlock, _ := pem.Decode(privateKeyBytes)
if privateKeyBlock == nil {
fmt.Println("failed to decode private key")
return privateKey, publicKey, errors.New("failed to decode private key")
return privateKey, errors.New("failed to decode private key")
}

privateKey, privateKeyErr := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if privateKeyErr != nil {
fmt.Println("failed to parse private key PEM block", privateKeyErr)
return privateKey, publicKey, errors.New("failed to parse private key PEM block")
return privateKey, errors.New("failed to parse private key PEM block")
}

publicKeyBytes, publicKeyBytesErr := os.ReadFile("jwtRS256.key.pub")
if publicKeyBytesErr != nil {
return privateKey, publicKey, errors.New("public key does not exist or cannot be read. Run gen-rsa-key.sh to generate a key pair")
}
return privateKey, nil
}

func GetRSAPublicKey() (*rsa.PublicKey, error) {
var publicKey *rsa.PublicKey

publicKeyStr := os.Getenv(RSA_PUBLIC_KEY)

publicKeyBytes := []byte(publicKeyStr)

publicKeyBlock, _ := pem.Decode(publicKeyBytes)
if publicKeyBlock == nil {
fmt.Println("failed to decode public key")
return privateKey, publicKey, errors.New("failed to decode public key")
return publicKey, errors.New("failed to decode public key")
}

publicKeyInt, publicKeyIntErr := x509.ParsePKIXPublicKey(publicKeyBlock.Bytes)
if publicKeyIntErr != nil {
fmt.Println("failed to parse public key PEM block", publicKeyIntErr)
return privateKey, publicKey, errors.New("failed to parse public key PEM block")
return publicKey, errors.New("failed to parse public key PEM block")
}

publicKey, _ = publicKeyInt.(*rsa.PublicKey)

return privateKey, publicKey, nil
return publicKey, nil
}

func checkRSAKeys() error {
_, privateKeyError := GetRSAPrivateKey()

if privateKeyError != nil {
return privateKeyError
}

_, publicKeyError := GetRSAPublicKey()

if publicKeyError != nil {
return publicKeyError
}

return nil
}

func setupServer() *gin.Engine {
client := setupMongoClient()

InitDatabase(AUTH_DB_NAME, client)
initDbErr := InitDatabase(AUTH_DB_NAME, client)

if initDbErr != nil {
log.Fatal("Error Initializing Database", initDbErr)
}

r := gin.Default()
r.GET("/", func(ctx *gin.Context) {
// ctx.JSON(200, gin.H{
// "message": "Hello!",
// })
ctx.Data(200, "text/html; charset=utf-8", make([]byte, 0))
})

Expand All @@ -140,18 +175,22 @@ func setupServer() *gin.Engine {
return
}

_, loginError := LogUserIn(body, ctx, client)
token, loginError := LogUserIn(body, ctx, client)

if loginError != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": loginError.Error()})
return
}

// if !hashIsGood {
// ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid Nonce"})
// }
ctx.JSON(200, gin.H{
"token": token,
})
})

r.POST("/verify-token", func(ctx *gin.Context) {})

ctx.JSON(200, gin.H{})
r.GET("/public-key", func(ctx *gin.Context) {
ctx.String(200, os.Getenv(RSA_PUBLIC_KEY))
})

return r
Expand Down
Loading

0 comments on commit 1456cb0

Please sign in to comment.