Closed up2pixy closed 7 years ago
I'd remove the required scopes property on our middleware and see if that changes anything.
Hi @leastprivilege , thank you for replying. After I commented out the required scope line, the AAD JWT is valid but the request with token issued from local simple auth server still return error 500, with a little different error:
ExceptionMessage=Sequence contains more than one element
ExceptionType=System.InvalidOperationException
Message=An error has occurred.
StackTrace=
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at Microsoft.Owin.Security.AuthenticationManager.<AuthenticateAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.HostAuthenticationFilter.<AuthenticateAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
Please help...
did you set the authentication type to a unique value on each MW? That's an OWIN requirement.
Ah! It works! Thank you very much @leastprivilege !!!
@leastprivilege Sorry but I need reopen this issue. I can use multiple MW now with unique AuthenticationType name. But the "insufficient_scope" issue is not resolved... Now the AAD is working with AccessTokenValidation MW, but the local auth server is still not working.
As a workaround I added "scope" claim with same required value when I issue token from local auth server. Then when I bring the token to the api, 2 identical identities are added. I believe one is from "UseOAuthBearerAuthentication", one is from "UseIdentityServerBearerTokenAuthentication" Is there anything wrong when I build my own ApplicationOAuthProvider? or it's a issue of AccessTokenValidation MW?
Are you sure that each middleware has a unique authentication type?
When I stop the pipeline by breaking at next.Invoke();
I see the authentication type is different.. So I think it's different? Here is what I set in the ConfigureAuth
app.UseOAuthAuthorizationServer(
new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/Token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(7),
Provider = new ApplicationOAuthProvider("self"),
AuthenticationType = "LocalBearer",
});
app.UseOAuthBearerAuthentication(
new OAuthBearerAuthenticationOptions
{
AuthenticationType = "LocalBearer"
});
app.UseIdentityServerBearerTokenAuthentication(
new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://login.3rdpartyIS3server.fake/",
AuthenticationType = "IS3Bearer",
RequiredScopes = new[] { "test-scope" },
ClientId = ConfigurationManager.AppSettings["IS3:ClientId"],
ClientSecret = ConfigurationManager.AppSettings["IS3:ClientSecret"],
NameClaimType = "sub",
});
Please help..
The scope validation should only kick in if the IS3Bearer
middleware produces a result. I think there is even a test for it in the solution. This confuses me.
This is weird.. When I bring the token issue by my own ApplicationOAuthProvider("self")
I still get the result at line 60 in ScopeRequirementMiddleware.cs
var result = await context.Authentication.AuthenticateAsync(_options.AuthenticationType);
Any clue to debug this? Something wrong in my ApplicationOAuthProvider
?
does the problem only exist for your own oauth provider - or also for AAD tokens?
The problem only exists for my own oauth provider... But when I check the token got from AAD, the AuthenticationType
is "JWT"
but not the value "AADBearer"
I set in the middleware... I'm wondering if it's related?
did you ever resolve that?
No I haven't.... Not sure if it's my ApplicationOAuthProvider
issue. Would you like to take a look?
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;
public ApplicationOAuthProvider(string publicClientId)
{
if (publicClientId == null)
{
throw new ArgumentNullException("publicClientId");
}
_publicClientId = publicClientId;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, context.Scope[0], "LocalBearer");
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager, context.Scope[0], CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
Uri expectedRootUri = new Uri(context.Request.Uri, "/");
if (expectedRootUri.AbsoluteUri == context.RedirectUri)
{
context.Validated();
}
}
return Task.FromResult<object>(null);
}
public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName }
};
return new AuthenticationProperties(data);
}
}
anything you want to add? Or can I close this?
I didn't resolve this... Now I disabled my own OAuth provider to bypass this issue...
There are two lines in the configuration that say:
AuthenticationType = "LocalBearer"
Hi, I'm sorry for the dumb question. I'm trying to make my API valid the token issued by IdentityServer3(provided by 3rd party) and the JWT from Azure AD, and the token from MSA, and the token issued by the API's own simple OAuth Authorization Server. So I'm like app.UseOAuthAuthorizationServer(...) app.UseMicrosoftAccountAuthentication(...) app.UseWindowsAzureActiveDirectoryBearerAuthentication(...) app.UseIdentityServerBearerTokenAuthentication(...)
The token validation was working until I added the last line above. It looks like the Authorization part in http request header is always caught by the IdentityServer3.AccessTokenValidation MW .
The token issued by local AS is no longer valid. I got the error 500 with following message when I provide the bearer token issued by local AS:
And if I provide the token from Azure AD, I will get error 403 with cookie:
WWW-Authenticate: Bearer error="insufficient_scope"
Could you please tell me how to make all validation methods work together? Thanks!