From a6df4ae96b14ccf66fd4f13e5a98706778d81c33 Mon Sep 17 00:00:00 2001 From: jinguoqiang Date: Tue, 18 May 2021 23:43:34 +0900 Subject: [PATCH 1/3] [add] env AWS_REGION --- app/register.go | 6 ++++++ go.mod | 2 +- go.sum | 29 +++++++++++++++++------------ main.go | 2 +- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/register.go b/app/register.go index 71b4404..51d2d92 100644 --- a/app/register.go +++ b/app/register.go @@ -28,6 +28,12 @@ func (a *App) Register(w http.ResponseWriter, r *http.Request) { }, } + // Compute secret hash based on client secret. + if a.AppClientSecret != "" { + secretHash := computeSecretHash(a.AppClientSecret, username, a.AppClientID) + user.SecretHash = aws.String(secretHash) + } + _, err := a.CognitoClient.SignUp(user) if err != nil { fmt.Println(err) diff --git a/go.mod b/go.mod index 565897b..c818af0 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/br4in3x/golang-cognito-example go 1.13 -require github.com/aws/aws-sdk-go v1.31.14 +require github.com/aws/aws-sdk-go v1.38.40 diff --git a/go.sum b/go.sum index b2d64ee..ee958a3 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,28 @@ -github.com/aws/aws-sdk-go v1.31.14 h1:uRC2riabEXPMHl1CDylsfCod5DKjiOSXhYvxg/Eb9V8= -github.com/aws/aws-sdk-go v1.31.14/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.38.40 h1:VVqBFV24tGgXR11tFXPjmR+0ItbnUepbuQjdmhgu3U0= +github.com/aws/aws-sdk-go v1.38.40/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 2ec9a38..02c4270 100644 --- a/main.go +++ b/main.go @@ -52,7 +52,7 @@ func Call(a *app.App, w http.ResponseWriter, r *http.Request) { } func main() { - conf := &aws.Config{Region: aws.String("us-east-1")} + conf := &aws.Config{Region: aws.String(os.Getenv("AWS_REGION"))} sess, err := session.NewSession(conf) if err != nil { panic(err) From 5956764435385f889858ef04aecd42781544d04f Mon Sep 17 00:00:00 2001 From: jinguoqiang Date: Tue, 18 May 2021 23:54:51 +0900 Subject: [PATCH 2/3] [fix] README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8292887..4a766c3 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This example code demonstrates how to use AWS Cognito with AWS Go SDK in a form 3. Verify user's phone 4. Login with username or refresh token -In order this solution to work, you need to have AWS credentials configured (file `.aws/configuration` exists) and User Pool created in AWS Console. You have to disable "Remember device" and enable "Sms second-factor" on authentication tab. +In order this solution to work, you need create User Pool in AWS Console. You have to disable "Remember device" and enable "Sms second-factor" on authentication tab. When the app client is created, in it's settings select "Enable username-password (non-SRP) flow for app-based authentication (USER_PASSWORD_AUTH)". @@ -31,13 +31,13 @@ go build -o ./build/cognito Without client secret: ```go -AWS_PROFILE=XXX COGNITO_APP_CLIENT_ID=XXX COGNITO_USER_POOL_ID=XXX PORT=8080 ./build/cognito +AWS_REGION=XXX COGNITO_APP_CLIENT_ID=XXX COGNITO_USER_POOL_ID=XXX PORT=8080 ./build/cognito ``` With client secret: ```go -AWS_PROFILE=XXX COGNITO_APP_CLIENT_ID=XXX COGNITO_APP_CLIENT_SECRET=XXX COGNITO_USER_POOL_ID=XXX PORT=8080 ./build/cognito +AWS_REGION=XXX COGNITO_APP_CLIENT_ID=XXX COGNITO_APP_CLIENT_SECRET=XXX COGNITO_USER_POOL_ID=XXX PORT=8080 ./build/cognito ``` It's worth noting that in production environment you should not pass client secrets this way because with adequate permissions it's possible to read environmental variables of a running process. Also if you call a command that way, secret hash will be stored in your shell history. You should keep those issues in mind and mitigate them in your enviroment. From 3798c12e284d5243d238487512fab6826b6d7fb7 Mon Sep 17 00:00:00 2001 From: jinguoqiang Date: Wed, 2 Jun 2021 21:47:31 +0900 Subject: [PATCH 3/3] [add] deal new_password_required --- app/login.go | 13 ++++ app/new_password_required.go | 44 +++++++++++++ main.go | 2 + static/new_password_required.html | 104 ++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 app/new_password_required.go create mode 100644 static/new_password_required.html diff --git a/app/login.go b/app/login.go index ee2d4d9..93f98bd 100644 --- a/app/login.go +++ b/app/login.go @@ -5,9 +5,11 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/base64" + "encoding/json" "fmt" "net/http" + "net/url" "github.com/aws/aws-sdk-go/aws" @@ -70,5 +72,16 @@ func (a *App) Login(w http.ResponseWriter, r *http.Request) { return } + if res.ChallengeName != nil && *res.ChallengeName == "NEW_PASSWORD_REQUIRED" { + params = map[string]*string{ + "username": aws.String(username), + "session": res.Session, + } + b, _ := json.Marshal(params) + s := url.QueryEscape(string(b)) + http.Redirect(w, r, fmt.Sprintf("/new_password_required?params=%s", s), http.StatusFound) + return + } + http.Redirect(w, r, fmt.Sprintf("/login?authres=%s", res.AuthenticationResult), http.StatusFound) } diff --git a/app/new_password_required.go b/app/new_password_required.go new file mode 100644 index 0000000..44066d3 --- /dev/null +++ b/app/new_password_required.go @@ -0,0 +1,44 @@ +package app + +import ( + "fmt" + "log" + "net/http" + + "github.com/aws/aws-sdk-go/aws" + cognito "github.com/aws/aws-sdk-go/service/cognitoidentityprovider" +) + +// NewPasswordRequired handles set new password. +func (a *App) NewPasswordRequired(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + + username := r.Form.Get("username") + password := r.Form.Get("password") + session := r.Form.Get("session") + + params := map[string]*string{ + "USERNAME": aws.String(username), + "NEW_PASSWORD": aws.String(password), + } + // Compute secret hash based on client secret. + if a.AppClientSecret != "" { + secretHash := computeSecretHash(a.AppClientSecret, username, a.AppClientID) + + params["SECRET_HASH"] = aws.String(secretHash) + } + chall := &cognito.RespondToAuthChallengeInput{ + ChallengeName: aws.String("NEW_PASSWORD_REQUIRED"), + ClientId: aws.String(a.AppClientID), + ChallengeResponses: params, + Session: aws.String(session), + } + res, err := a.CognitoClient.RespondToAuthChallenge(chall) + if err != nil { + log.Println(err) + http.Redirect(w, r, fmt.Sprintf("/login?message=%s", err.Error()), http.StatusSeeOther) + return + } + + http.Redirect(w, r, fmt.Sprintf("/login?authres=%s", res.AuthenticationResult), http.StatusFound) +} diff --git a/main.go b/main.go index 02c4270..d69eae9 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,8 @@ func Call(a *app.App, w http.ResponseWriter, r *http.Request) { a.OTP(w, r) case "/register": a.Register(w, r) + case "/new_password_required": + a.NewPasswordRequired(w, r) case "/username": a.Username(w, r) default: diff --git a/static/new_password_required.html b/static/new_password_required.html new file mode 100644 index 0000000..4f3d1a9 --- /dev/null +++ b/static/new_password_required.html @@ -0,0 +1,104 @@ + + + + + + + + NEW_PASSWORD_REQUIRED + + + +
+
+

NEW_PASSWORD_REQUIRED

+ + +
+
+ + Username / Password +
+
+
+
+ + + +
+
+ + +
+ +
+
+
+

+ ← Back to index +

+ + +
+
+ + + + +