Skip to content

An extension library to assist in the Amazon Cognito User Pools authentication process

License

Notifications You must be signed in to change notification settings

GabrielHare/aws-sdk-net-extensions-cognito

 
 

Repository files navigation

.NET on AWS Banner

Amazon Cognito Authentication Extension Library

nuget

Amazon.Extensions.CognitoAuthentication simplifies the authentication process of Amazon Cognito User Pools for .NET developers.

It allows you to use various authentication methods for Amazon Cognito User Pools with only a few short method calls, and makes the process intuitive.

Learn more about Amazon Cognito User Pools.

This library targets the .NET Standard 2.0 and introduces the following dependencies:

Getting Started

To take advantage of this library, set up an AWS account and install the AWS SDK for .NET as described in Getting Started with the AWS SDK for .NET.

While this library is in development, you will need to build it manually.

Create a new project in Visual Studio and add the Amazon Cognito Authentication Extension Library as a reference to the project.

Using the library to make calls to the Amazon Cognito Identity Provider API from the AWS SDK for .NET is as simple as creating the necessary CognitoAuthentication objects and calling the appropriate AmazonCognitoIdentityProviderClient methods. The principal Amazon Cognito authentication objects are:

  • CognitoUserPool objects store information about a user pool, including the poolID, clientID, and other pool attributes.
  • CognitoUser objects contain a user’s username, the pool they are associated with, session information, and other user properties.
  • CognitoDevice objects include device information, such as the device key.

Authenticating with Secure Remote Protocol (SRP)

Instead of implementing hundreds of lines of cryptographic methods yourself, you now only need to create the necessary AmazonCognitoIdentityProviderClient, CognitoUserPool, CognitoUser, and InitiateSrpAuthRequest objects and then call StartWithSrpAuthAsync:

using Amazon.Runtime;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;

public async void AuthenticateWithSrpAsync()
{
    var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), FallbackRegionFactory.GetRegionEndpoint());
    var userPool = new CognitoUserPool("poolID", "clientID", provider);
    var user = new CognitoUser("username", "clientID", userPool, provider);

    var password = "userPassword";

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
    {
        Password = password
    }).ConfigureAwait(false);
}

The AuthenticationResult property of the AuthFlowResponse object contains the user’s session tokens if the user was successfully authenticated. If more challenge responses are required, this field is null and the ChallengeName property describes the next challenge, such as multi-factor authentication. You would then call the appropriate method to continue the authentication flow.

Authenticating with Multiple Forms of Authentication

Continuing the authentication flow with challenges, such as with NewPasswordRequired and Multi-Factor Authentication (MFA), is simpler as well.

The following code shows one way to check the challenge type and get appropriate responses for MFA and NewPasswordRequired challenges. This processing might be necessary as the authentication flow proceeds, depending on the properties of the AuthFlowResponse object that was retrieved earlier.

while (authResponse.AuthenticationResult == null)
{
    if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
    {
        Console.WriteLine("Enter your desired new password:");
        string newPassword = Console.ReadLine();

        authResponse = 
            await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest()
            {
                SessionID = authResponse.SessionID,
                NewPassword = newPassword
            }).ConfigureAwait(false);
    }
    else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
    {
        Console.WriteLine("Enter the MFA Code sent to your device:");
        string mfaCode = Console.ReadLine();

        authResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest()
        {
                SessionID = authResponse.SessionID,
                MfaCode = mfaCode
        }).ConfigureAwait(false);
        }
        else
        {
            Console.WriteLine("Unrecognized authentication challenge.");
            break;
        }
}

Learn more about Amazon Cognito User Pool Authentication Flow.

Authenticating with Different Levels of Authentication

After a user is authenticated by using the Amazon Cognito Authentication Extension Library, you can then allow them to access specific AWS resources.

To allow users to access specific AWS resources, you must create an identity pool through the Amazon Cognito Federated Identities console.

You can also specify different roles for both unauthenticated and authenticated users so that they can access different resources. These roles can be changed in the IAM console where you can add or remove permissions in the Action field of the role’s attached policy. Then, using the appropriate identity pool, user pool, and Amazon Cognito user information, calls can be made to different AWS resources.

The following code shows how a user, who was authenticated with SRP, can access various S3 buckets as permitted by the associated identity pool’s role.

using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.CognitoIdentity;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;

public async void GetS3BucketsAsync()
{
    var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(),
                                                            FallbackRegionFactory.GetRegionEndpoint());
    var userPool = new CognitoUserPool("poolID", "clientID", provider);
    var user = new CognitoUser("username", "clientID", userPool, provider);

    var password = "userPassword";

    await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
    {
        Password = password
    }).ConfigureAwait(false);

    var credentials = 
        user.GetCognitoAWSCredentials("identityPoolID", RegionEndpoint.<YourIdentityPoolRegion>);

    using (var client = new AmazonS3Client(credentials))
    {
        ListBucketsResponse response = 
            await client.ListBucketsAsync(new ListBucketsRequest()).ConfigureAwait(false);

        foreach (S3Bucket bucket in response.Buckets)
        {
            Console.WriteLine(bucket.BucketName);
        }
    }
}

Authenticating using a Refresh Token from a Previous Session

Access and ID tokens provided by Cognito are only valid for one hour but the refresh token can be configured to be valid for much longer. Below is an example of how to retrieve new Access and ID tokens using a refresh token which is still valid.

See here to learn more about using the tokens returned by Amazon Cognito.

using Amazon;
using Amazon.Runtime;
using Amazon.CognitoIdentity;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;

public async Task GetCredsFromRefreshAsync(string refreshToken, string deviceKey)
{
    using var provider = new AmazonCognitoIdentityProviderClient();
    var userPool = new CognitoUserPool("poolID", "clientID", provider);

    var user = new CognitoUser("username", "clientID", userPool, provider, "clientSecret")
    {
        SessionTokens = new CognitoUserSession(null, null, refreshToken, DateTime.UtcNow, DateTime.UtcNow.AddHours(1))
    };

    // If the user pool is configured to track and remember user devices, it must be attached to the user before initiating the flow:
    // user.Device = new CognitoDevice(new DeviceType { DeviceKey = deviceKey }, user);

    var authResponse = await user.StartWithRefreshTokenAuthAsync(new InitiateRefreshTokenAuthRequest
    {
        AuthFlowType = AuthFlowType.REFRESH_TOKEN_AUTH
    });
}

Other Forms of Authentication

In addition to SRP, NewPasswordRequired, MFA and Refresh the Amazon Cognito Authentication Extension Library offers an easier authentication flow for the following:

  • Custom – Begins with a call to StartWithCustomAuthAsync(InitiateCustomAuthRequest customRequest)
  • AdminNoSRP – Begins with a call to StartWithAdminNoSrpAuth(InitiateAdminNoSrpAuthRequest adminAuthRequest)

Getting Help

We use the GitHub issues for tracking bugs and feature requests and have limited bandwidth to address them.

If you think you may have found a bug, please open an issue

Contributing

We welcome community contributions and pull requests. See CONTRIBUTING for information on how to set up a development environment and submit code.

Additional Resources

AWS .NET GitHub Home Page
GitHub home for .NET development on AWS. You'll find libraries, tools, and resources to help you build .NET applications and services on AWS.

AWS Developer Center - Explore .NET on AWS
Find .NET code samples, step-by-step guides, videos, blog content, tools, and information about live events all in one place.

AWS Developer Blog - .NET
Come and see what .NET developers at AWS are up to! Learn about new .NET software announcements, guides, and how-to's.

@dotnetonaws Follow us on twitter!

License

Libraries in this repository are licensed under the Apache 2.0 License.

See LICENSE and NOTICE for more information.

About

An extension library to assist in the Amazon Cognito User Pools authentication process

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%