Last post May 13, 2015 09:41 PM by gtscdsi
May 08, 2015 08:33 AM|stephan.steiner|LINK
I'm trying to get to the bottom of authentication. I have a controller where I need basic auth to verify the credentails against a database. So I had a look at the Authentication Filters in Web APi2 (http://www.asp.net/web-api/overview/security/authentication-filters)
and it links to code samples on codeplex. I downloaded that sample and tried debugging it. My first request seems to hit BasicAuthenticationAttribute.AuthenticatAsync, and as it contains no authorization header, it gets a 401 back. Then, using the sample client
or a web browser I hit the home controller again and this time it gets a 401 immediately, it doesn't hit BasicAuthenticationAttribute.AuthenticateAsync anymore. It seems like the very first request to the controller does hit AuthenticateAsync but subsequent
requests do not
Is there anything in the sample that needs to be modified for it to work? I even tried changing the Client sample program to send the first request with credentials
await TryRequestAsync(client, CreateBasicCredentials("SampleUser", "secret"));
but again it gets a 401 response. So I must be missing something.. that sample is supposed to work out of the box, isn't it?
@edit: I extracted the authentication bit and moved it to my own owin based project. If I decorate a controller method, it hits BasicAuthenticationAttribute.AuthenticateAsync on every request. So when I hit my controller method without authentication, I
see it not having an authorization header, and returning 401 unauthorized. Then I get a credential prompt, enter the credentials, and send the request again. Again it hits BasicAuthenticationAttribute.AuthenticateAsync, I see it extracting credentials, they
are verified, and the principal is properly set and everything proceed as desired. But the question remains why the sample won't work properly.
May 13, 2015 07:37 AM|gtscdsi|LINK
Thank you post here.
The example project would run good without any code change, it acts as article says.
The authentication filter is a required step in the handling pipe line, so every request from the user or browser should hit this filter to process authentication.
The link in you post explains very well for authentication filter, may be you should check your project again or share with us more detailed information that we can try to investigate.
May 13, 2015 08:25 AM|stephan.steiner|LINK
I Downloaded the source, extracted it, started the project (opens up a webbrowser asking for credentials), then started the sample client. Does it work for you if you do exactly that and nothing more?
This is on VS2013 U3, .NET 4.5.2, none beta or RC of the next edition code every touched this machine.
May 13, 2015 09:41 PM|gtscdsi|LINK
Yes it works for me. I guess you could try to insert a debug point at AuthenticateAsync() in IdentityBasicAuthenticationAtttibute class and launch project with debug model to see if the process could get into the debug point and go through this method step
by step to see if identity is null or not null.
public class IdentityBasicAuthenticationAttribute : BasicAuthenticationAttribute
protected override async Task<IPrincipal> AuthenticateAsync(string userName, string password, CancellationToken cancellationToken)
// Break point here
UserManager<IdentityUser> userManager = CreateUserManager();
cancellationToken.ThrowIfCancellationRequested(); // Unfortunately, UserManager doesn't support CancellationTokens.
IdentityUser user = await userManager.FindAsync(userName, password);
if (user == null)
// No user with userName/password exists.
// Create a ClaimsIdentity with all the claims for this user.
cancellationToken.ThrowIfCancellationRequested(); // Unfortunately, IClaimsIdenityFactory doesn't support CancellationTokens.
ClaimsIdentity identity = await userManager.ClaimsIdentityFactory.CreateAsync(userManager, user, "Basic");
return new ClaimsPrincipal(identity);
private static UserManager<IdentityUser> CreateUserManager()
return new UserManager<IdentityUser>(new UserStore<IdentityUser>(new UsersDbContext()));