Giter Club home page Giter Club logo

cognito-srp's Introduction

cognito-srp

Build Status Go Report Card Maintainability Test Coverage

This is almost a direct port of capless/warrant

All crypto functions are tested against equivalent values produced by warrant

  • v2 - Removed dependency on aws-sdk-go-v2
  • v3 - Migrate to map[string]*string types for better compatability with aws-sdk-go-v2
  • v4 - Migrate back to map[string]string types as aws-sdk-go-v2 reverted their API changes

Usage

package main

import (
	"context"
	"fmt"
	"time"

	cognitosrp "github.com/alexrudd/cognito-srp/v4"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	cip "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
	"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
)

func main() {
	// configure cognito srp
	csrp, _ := cognitosrp.NewCognitoSRP("user", "pa55w0rd", "eu-west-1_myPoolId", "client", nil)

	// configure cognito identity provider
	cfg, _ := config.LoadDefaultConfig(
		config.WithRegion("eu-west-1"),
		config.WithCredentialsProvider(aws.AnonymousCredentials{}),
	)
	svc := cip.NewFromConfig(cfg)

	// initiate auth
	resp, err := svc.InitiateAuth(context.Background(), &cip.InitiateAuthInput{
		AuthFlow:       types.AuthFlowTypeUserSrpAuth,
		ClientId:       aws.String(csrp.GetClientId()),
		AuthParameters: csrp.GetAuthParams(),
	})
	if err != nil {
		panic(err)
	}

	// respond to password verifier challenge
	if resp.ChallengeName == types.ChallengeNameTypePasswordVerifier {
		challengeResponses, _ := csrp.PasswordVerifierChallenge(resp.ChallengeParameters, time.Now())

		resp, err := svc.RespondToAuthChallenge(context.Background(), &cip.RespondToAuthChallengeInput{
			ChallengeName:      types.ChallengeNameTypePasswordVerifier,
			ChallengeResponses: challengeResponses,
			ClientId:           aws.String(csrp.GetClientId()),
		})
		if err != nil {
			panic(err)
		}

		// print the tokens
		fmt.Printf("Access Token: %s\n", *resp.AuthenticationResult.AccessToken)
		fmt.Printf("ID Token: %s\n", *resp.AuthenticationResult.IdToken)
		fmt.Printf("Refresh Token: %s\n", *resp.AuthenticationResult.RefreshToken)
	} else {
		// other challenges await...
	}
}

cognito-srp's People

Contributors

3oris avatar alexrudd avatar peterallworth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

cognito-srp's Issues

Cognito returns NotAuthorizedException when app client secret is present

I recently encountered this error when I updated to v4 from v2 and supplied a clientId with a non-nil clientSecret.

operation error Cognito Identity Provider: RespondToAuthChallenge, https response error StatusCode: 400, 
RequestID: e77305a6-8f2a-4a19-9fd6-b420d60d05fa, NotAuthorizedException: Unable to verify secret hash for client...

The issue appears to be that the v2 code uses the username supplied in the challenge parameters for calculating the secret hash whereas the v4 code uses the username saved in the CognitoSRP structure.

I've tested a fix for this in my fork peterallworth/cognito-srp and it appears to work, as does reverting to v2.

Remove cognitoidentityprovider dependency?

What is the reason to keep dependency to aws sdk cognito provider? I see it in the code only once as referencing type RespondToAuthChallengeInput. It's not used in your tests, too.

Base aws is used just to make string ref - aws.String. This may be replaced by by ref to string.

My rationale: I'm building CLI app that uses your library to auth without need to construct cip client, just user credentials, same like web app. It's quite a big dep.

I'm golang novice so maybe I'm wrong about the need of having this.

Readme example fails to work

Yo! Trying to get auth token from cognito, and got the readme example to start with, but suddenly got very frustrating error. (all the cred info is stubbed ofc.)

$ go run main.go
panic: unable to covert "username" to big Int

goroutine 1 [running]:
github.com/alexrudd/cognito-srp/v3.hexToBig(0xc00017c0e0, 0xe, 0x0)
	/home/shvedchenko/go/pkg/mod/github.com/alexrudd/cognito-srp/[email protected]/cognitosrp.go:217 +0x12b
github.com/alexrudd/cognito-srp/v3.(*CognitoSRP).PasswordVerifierChallenge(0xc0000da100, 0xc0005c3d20, 0xbfebaf3f9424e7f6, 0x6aeeb356, 0xa1aec0, 0x0, 0x0, 0xc0004a21e0)
	/home/shvedchenko/go/pkg/mod/github.com/alexrudd/cognito-srp/[email protected]/cognitosrp.go:144 +0x2f9
main.main()
	/home/shvedchenko/workspace/testCognito/main.go:51 +0x6f0

As you can see my api username is somehow passed to a hexToBig function which is not taking a USERNAME key of challengeParams anywhere.

Here is my go.mod

module testCognito

go 1.15

require (
	github.com/alexrudd/cognito-srp/v3 v3.0.0
	github.com/aws/aws-sdk-go-v2 v0.30.0
	github.com/aws/aws-sdk-go-v2/config v0.3.0
	github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v0.30.0
)

And here is my whole main.go, which is almost the same as your readme example. The only huge difference is that I'm three times casting map[string]*string to map[string]string and back because thats what the funcs expecting for parameters. And that is may be the root of ther problem. Although I've inspected the challengeParameters map and there was the SALT key and SRP_B key, and the values was hex, not my username value. Which is not making me happy anyway. Will do a delve debug session tomorrow, but hoping that there is someting significant I've found and should share with you.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	cognitosrp "github.com/alexrudd/cognito-srp/v3"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	cip "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
	"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
)

func main() {
	// configure cognito srp
	csrp, err := cognitosrp.NewCognitoSRP("username", "superduperpass", "ap-southeast-2_myPoolId", "client", nil)
	if err != nil {
		log.Fatal(err)
	}

	// configure cognito identity provider
	cfg, _ := config.LoadDefaultConfig(
		config.WithRegion("ap-southeast-2"),
		config.WithCredentialsProvider(aws.AnonymousCredentials{}),
	)
	svc := cip.NewFromConfig(cfg)

	gap := make(map[string]string)
	for k, v := range csrp.GetAuthParams() {
		gap[k] = *v
	}

	// initiate auth
	resp, err := svc.InitiateAuth(context.Background(), &cip.InitiateAuthInput{
		AuthFlow:       types.AuthFlowTypeUserSrpAuth,
		ClientId:       aws.String(csrp.GetClientId()),
		AuthParameters: gap,
	})
	if err != nil {
		log.Fatal(err)
	}

	// respond to password verifier challenge
	chp := make(map[string]*string)
	// log.Fatalf("%+v\n", resp.ChallengeParameters)
	for k, v := range resp.ChallengeParameters {
		chp[k] = &v
	}

	if resp.ChallengeName == types.ChallengeNameTypePasswordVerifier {
		challengeResponses, _ := csrp.PasswordVerifierChallenge(chp, time.Now())
		chrs := make(map[string]string)
		for k, v := range challengeResponses {
			chrs[k] = *v
		}

		resp, err := svc.RespondToAuthChallenge(context.Background(), &cip.RespondToAuthChallengeInput{
			ChallengeName:      types.ChallengeNameTypePasswordVerifier,
			ChallengeResponses: chrs,
			ClientId:           aws.String(csrp.GetClientId()),
		})
		if err != nil {
			log.Fatal(err)
		}

		// print the tokens
		fmt.Printf("Access Token: %s\n", *resp.AuthenticationResult.AccessToken)
		fmt.Printf("ID Token: %s\n", *resp.AuthenticationResult.IdToken)
		fmt.Printf("Refresh Token: %s\n", *resp.AuthenticationResult.RefreshToken)
	} else {
		log.Fatal("hui")
	}
}

SRP doesn't authenticate reliably with client secret

The current implementation of PasswordVerifierChallenge doesn't reliably authenticate when authenticating via e-mail address using a client secret. It will yield a:

"An error occurred (NotAuthorizedException) when calling the RespondToAuthChallenge operation: Unable to verify secret hash for client"

As you can see in the official AWS java SDK, the right way to respond to an auth challenge request (https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUser.java#L2914 ) is to use the internal user name from the challenge paramteters and use it for secret hash calculation (https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUser.java#L2955 ) as well as username in the srpAuthResponse (https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUser.java#L2964 )

Please find attached the pull request that fixes this issue. #2

FYI: I also created an issue and pull request in https://github.com/capless/warrant/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.