aws / aws-aspnet-cognito-identity-provider

ASP.NET Core Identity Provider for Amazon Cognito
https://aws.amazon.com/developer/language/net/
Apache License 2.0
215 stars 89 forks source link

'Missing Authentication Token' when creating user #66

Closed andyfurniss4 closed 5 years ago

andyfurniss4 commented 5 years ago

Hi there,

I'm trying to set us the registration flow for a new website. I have followed the guide for setting up the Identity in Startup.cs and also copied the sample Register page code. You can see both below.

Startup.cs

// Identity
var awsCredentials = new BasicAWSCredentials(this.config["AWS:AccessKey"], this.config["AWS:SecretKey"]);
var cognitoClient = new AmazonCognitoIdentityProviderClient(awsCredentials, RegionEndpoint.EUWest2);
var userPool = new CognitoUserPool(
    config["Cognito:PoolId"],
    config["Cognito:ClientId"],
    cognitoClient,
    config["Cognito:ClientSecret"]);

services.AddCognitoIdentity();
services.AddSingleton<IAmazonCognitoIdentityProvider>(cognitoClient);
services.AddSingleton<CognitoUserPool>(userPool);

services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();

services
    .ConfigureApplicationCookie(o =>
    {
        o.Cookie.HttpOnly = true;
        o.ExpireTimeSpan = TimeSpan.FromHours(1);
        o.SlidingExpiration = true;
        o.LoginPath = "/Identity/Account/Login";
        o.LogoutPath = "/Identity/Account/Logout";
    });

services
    .Configure<SecurityStampValidatorOptions>(o =>
    {
        o.ValidationInterval = TimeSpan.FromHours(1);
    });

Register.cshtml.cs

using Amazon.AspNetCore.Identity.Cognito;
using Amazon.Extensions.CognitoAuthentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Serilog;
using Newtonsoft.Json;
using System;

namespace TAP.Extranet.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class RegisterModel : PageModel
    {
        private readonly ILogger logger;

        private readonly SignInManager<CognitoUser> signInManager;
        private readonly CognitoUserManager<CognitoUser> userManager;
        private readonly CognitoUserPool userPool;

        public RegisterModel(
            ILogger logger,
            SignInManager<CognitoUser> signInManager,
            UserManager<CognitoUser> userManager,
            CognitoUserPool userPool
            )
        {
            this.logger = logger;
            this.userManager = userManager as CognitoUserManager<CognitoUser>;
            this.signInManager = signInManager;
            this.userPool = userPool;
        }

        [BindProperty]
        public RegisterViewModel Input { get; set; }

        public string ReturnUrl { get; set; }

        public async Task OnGet(string returnUrl = null)
        {
            ReturnUrl = returnUrl;
        }

        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            if (ModelState.IsValid)
            {
                var user = userPool.GetUser(Input.Email);

                user.Attributes.Add(CognitoAttributesConstants.Name, Input.Name);
                user.Attributes.Add(CognitoAttributesConstants.FamilyName, Input.Surname);
                user.Attributes.Add(CognitoAttributesConstants.Email, Input.Email);

                user.Attributes.Add(ExtranetUserAttributes.OperatorName, Input.BusinessName);
                user.Attributes.Add(ExtranetUserAttributes.Approved, "0");

                var signInResult = await this.userManager.CreateAsync(user, Input.Password);

                if (signInResult.Succeeded)
                {
                    this.logger.Information($"New user account created: {JsonConvert.SerializeObject(Input)}");
                    RedirectToAction("Index", "Home");
                }

                this.logger.Warning($"Unable to create new user account! Errors: {string.Join("\n\r", signInResult.Errors)}. User details: {JsonConvert.SerializeObject(Input)}");

                foreach (var error in signInResult.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }

            // If we got this far, something failed, redisplay form
            return Page();
        }
    }
}

User Pool settings:

image

When calling await this.userManager.CreateAsync(user, Input.Password) I get the following exception:

Missing Authentication Token at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleException(IExecutionContext executionContext, HttpErrorResponseException exception) in E:\JenkinsWorkspaces\v3-trebuchet-release\AWSDotNetPublic\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\HttpErrorResponseExceptionHandler.cs:line 60 at Amazon.Runtime.Internal.ErrorHandler.ProcessException(IExecutionContext executionContext, Exception exception) in E:\JenkinsWorkspaces\v3-trebuchet-release\AWSDotNetPublic\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 212 at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in E:\JenkinsWorkspaces\v3-trebuchet-release\AWSDotNetPublic\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 104 at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.CredentialsRetriever.InvokeAsync[T](IExecutionContext executionContext) in E:\JenkinsWorkspaces\v3-trebuchet-release\AWSDotNetPublic\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CredentialsRetriever.cs:line 98 at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext) in E:\JenkinsWorkspaces\v3-trebuchet-release\AWSDotNetPublic\sdk\src\Core\Amazon.Runtime\Pipeline\RetryHandler\RetryHandler.cs:line 137 at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.ErrorCallbackHandler.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.MetricsHandler.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Extensions.CognitoAuthentication.CognitoUserPool.GetPasswordPolicyTypeAsync() at Amazon.AspNetCore.Identity.Cognito.CognitoPasswordValidator.ValidateAsync(UserManager1 manager, CognitoUser user, String password) at Amazon.AspNetCore.Identity.Cognito.CognitoUserManager1.ValidatePasswordInternal(TUser user, String password) at Amazon.AspNetCore.Identity.Cognito.CognitoUserManager1.CreateAsync(TUser user, String password, IDictionary2 validationData) at Test.Areas.Identity.Pages.Account.RegisterModel.OnPostAsync(String returnUrl) in C:\Projects\Test\Areas\Identity\Pages\Account\Register.cshtml.cs:line 115

Am I missing something obvious? Sorry if I am but I've used this package elsewhere (which didn't include registration) and it just worked so I'm a bit stuck! Let me know if you need to see any details of the User Pool from Cognito.

andyfurniss4 commented 5 years ago

Ignore this. I'm an idiot and I forgot to set my AWS credential environment variables. This can be closed.

Having said this, the error message given - 'Missing Authentication Token' - is not very helpful in directing you to the actual problem. Maybe can be improved?

assyadh commented 5 years ago

Unfortunately this error is in a deep level dependency of the AWS .NET SDK (AWSSDK.Core).

I can bring it up to the team to update the exception message, but I can't promise an eta for that.

andyfurniss4 commented 5 years ago

OK, no problem. Hopefully they get round to it sooner or later!

assyadh commented 5 years ago

Closing in favor of an internal issue