I'll try to be explicit.
I have a Front End app (MVC), it can communicate with a Facade Web Api (Resource) and get token from an authentication server.
My problem is I can't create an identity in MVC app. This is mu Startup class.
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}
When I try to go to a method controller decorated with [Authorize], I get 401 error instead to be redirected to Login page.
Please, I would appreciate any help, advice or example.
Regards,
Typically, unless your app is doing postback's you do not need to enable the cookie authentication with login path. That is for the oauth password login flow (grant_type) where you are internally authorizing your users against your identity database. If you're redirecting to an external authorization api (like facebook) then you don't need to set a login path in your application since the first authorization endpoint that gets hit is your external callback (after you send them to facebook, they will send them back to your external endpoint). The redirect you are getting is because cookie authentication is registered as active authentication mode so it redirects 401's to the login path you set (overriding other OWIN middleware).
If you want to house your authorization server in house, have a look at the link below, it will at the least get you setup with JWT support -
http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/
Related
I am using Microsoft Owin/Katana and implemented the social login authentication in a Web Forms and MVC application which is working perfectly.
I have a requirement to convert the implementation into an API (controllers). In my MVC application, I am calling this line of code inside the login controller,
HttpContext.GetOwinContext().Authentication.Challenge(properties, AuthenticationProvider);
The user is redirected to the login screen of the provider (i.e. Google, Facebook, Twitter).
I was hoping to achieve the following,
User call /api/login controller of my API and it checks the provider and then using the access key and secret key, it returns the login URL as string or JSON and the consumer of the API will redirect to that URl. This way the secret and access keys are not exposed and just the URL is returned.
The problem is that there is no way I am able to find to get the login request URL of the provider. The Challenge method is void and it just redirects the user which in case of an API is not acceptable.
I have used the following code in a Web API,
var properties = new AuthenticationProperties() { RedirectUri = this.RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
MessageRequest.GetOwinContext().Authentication.Challenge(properties, AuthenticationProvider);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = MessageRequest;
return Task.FromResult(response);
When I call the API using Postman then it returns the whole HTML of the login page. When I call the API URL directly in the browser then it redirects to the login page correctly but I just want to return the Url of the provider and the consumer should redirect itself.
Is there any way to achieve this?
my login and register methods are working well and i use the Claim when the user try to login or logout.
i saw many example of that ForgotMyPassword page but all of it using
private readonly UserManager<IdentityUser> _userManager; which is based on Microsoft.AspNetCore.Identity; . Can i do ForgotMyPassword action without using UserManager
?? im asking that Claim based authentication and authorization is what i need in my project.
can i use them both,if i can how can i do that ?
it would be so great if someone explain its clearly,regards
When users register, their information will be added to the database. You can pass the registered email of the user to the ForgotMyPassword action. Then send a verification code to the mailbox or send a link to make user redirect to another page to reset the password. Make the user finish changing the password.
You can both use authentication and authorization, they are responsible for different businesses. Authentication has cookie, jwt and other authentication service. cookie authentication is the built-in component. Identity has integrated it. You should have learn about it.
The another service is authorization. Authorization service only works after authentication is successful. It has many authorization methods, about claim-based authorization, when one user access the authorized action, it will go through the middleware app.UseAuthorization(). This middleware will check whether there is a claim corresponding to the action policy's claim. Because you have configured it in startup.
services.AddAuthorization(options=>
{
options.AddPolicy("Policy1",policy=>
{
policy.RequireClaim("claim1",new string[] {"value1","value2" });
});
});
On the authorized action.
[Authorize(Policy = "Policy1")]
public IActionResult get()
{
return Ok();
}
In this scenario, the user should have the claim Claim("claim1","value1") or Claim("claim1","value2").
In my ASP.Net Core app, I have implemented Microsoft External Login. I now wish to override the default login callback, which is listed by documentation to be https://localhost:5001/signin-microsoft, if of course running on localhost and on that port. The instructions on here then state that the callback override would be something like this: https://contoso.azurewebsites.net/.auth/login/microsoftaccount/callback.
I am a bit confused on where the callback is meant to be implemented. At the moment I have ExternalLoginCallback() callback method implemented in a base Controller class. But from looking at the above example, it doesn't look like it should be part of a controller.
Should the callback be inside Startup.cs, a Controller, or some other file I am not currently aware of?
The instructions on here then state that the callback override would be something like this: https://contoso.azurewebsites.net/.auth/login/microsoftaccount/callback.
That is related to built-in authentication and authorization support in Azure App service . Do you host your app in Azure App service ?
If yes :
If you enable the Authentication and authorizationfeature of the app service , that means you are using the built-in authentication and authorization support in Azure . That feature will take over the authentication and authorization of you application , that means authentication and authorization still works even you delete the external Azure AD authentication codes in your application . Then you could just :
Use Authentication and authorizationfeature of the app service , delete the Owin Microsoft Account authentication middleware related codes .
Disable Authentication and authorizationfeature of the app service, use Microsoft Account external login( Microsoft.AspNetCore.Authentication.MicrosoftAccount package) .
If no :
Then you should follow document : Microsoft Account external login . You can config the callback url by :
microsoftOptions.CallbackPath = "/home/about";
But if you are using the ASP.NET Identity template with Microsoft Account external login . After Microsoft authentication , asp.net will check whether user's identity exists in database . Since ASP.NET Core 2.1 and later provides ASP.NET Core Identity as a Razor Class Library. If you want to redirect user to another page after authentication , you can :
Scaffold Identity in ASP.NET Core projects: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-2.2&tabs=visual-studio
After that ,modify the redirect url in Areas.Identity.Pages.Account.Login.cshtml.cs:
public IActionResult OnPost(string provider, string returnUrl = null)
{
returnUrl = "/home/contact";
// Request a redirect to the external login provider.
var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
}
Scenario:
Both Web application and Web API need to be authenticated and protected from the server side.
Requirement:
Web application is serving the contents for the browser and browser should be calling Web API directly (i.e. Browser to API).
Question:
Is it possible to authenticate both Web APP and the API using tokens?
Any sample code or clear direction would be highly appreciated.
Normally web applications are authenticated using cookies and APIs are authenticated using tokens.There are some sample projects available here but they are either browser to API (SPA token based) or Server side Web App calling API from server to server.
UPDATE 1
App is saving the TokenValidationParameters and used bootstrapContext.Token within the app controller to grab for server to server communication.
As per #dstrockis, I'm trying to grab the id_token from the Web App soon after the end of validation (not within the app contrller).
I'm using SecurityTokenValidated invoker in OpenIdConnectAuthenticationOptions.Notifications within the Startup class. SecurityTokenValidated receives a parameter of type SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> but I'm not sure where to find the id_token within it. Method is below.
private OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(string policy)
{
return new OpenIdConnectAuthenticationOptions
{
// For each policy, give OWIN the policy-specific metadata address, and
// set the authentication type to the id of the policy
MetadataAddress = String.Format(aadInstance, tenant, policy),
AuthenticationType = policy,
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = clientId,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
//NEW METHOD INVOKE ************************************
//******************************************************
SecurityTokenValidated = OnSecurityTokenValidated
//******************************************************
},
Scope = "openid",
ResponseType = "id_token",
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
SaveSigninToken = true
},
};
}
//NEW METHOD ************************************
private Task OnSecurityTokenValidated(
SecurityTokenValidatedNotification<OpenIdConnectMessage,
OpenIdConnectAuthenticationOptions> arg)
{
//QUESTION ********************************************************
//How to find the just saved id_token using incoming parameter, arg
//*****************************************************************
return Task.FromResult(0);
}
UPDATE 2
Instead of SecurityTokenValidated, I tried AuthorizationCodeReceived and it's not getting called at all. As discussed here, my redirect url does have an ending slash as well.
Any Ideas?
Our ASP.NET OpenID Connect middleware which supports AAD B2C is built to rely on cookie authentication from a browser. It doesn't accept tokens in a header or anything like that for securing web pages. So I'd say if you want to serve HTML from your web app in the classic way, you need to use cookies to authenticate requests to the web app.
You can definitely get & store tokens within the browser and use those to access your web API, even if you use cookies to authenticate to the web app. There's two patterns I'd recommend:
Perform the initial login using the OpenID Connect Middleware, initiating the flow from the server side as described in the samples. Once the flow completes, the middleware will validate the resulting id_token and drop cookies in the browser for future requests. You can instruct the middleware to save the id_token for later use by using the line of code written here. You can then somehow pass that id_token down to your browser, cache it, and use it to make requests to the API.
The other pattern is the inverse. Start by initiating the login from javascript, using the single page app pattern from the B2C documentation. Cache the resulting id_tokens in the browser, and use them to make API calls. But when the login completes, you can send a request to your web app with the id_token in the body, triggering the OpenID Connect middleware to process the request and issue a session cookie. If you want to know the format of that request, I'd recommend inspecting a regular server side OpenID Connect flow.
Found the answer to my own question and adding here for the future reference.
After a successful validation, id_token can be accessed by invoking the SecurityTokenValidated notification. Code sample is below.
private Task OnSecurityTokenValidated(
SecurityTokenValidatedNotification<OpenIdConnectMessage,
OpenIdConnectAuthenticationOptions> arg)
{
//Id Token can be retrieved as below.
//**************************************
var token = arg.ProtocolMessage.IdToken;
return Task.FromResult(0);
}
However, saving this directly into a browser cookie may not be secure.
I've got a WebAPI instance running in Azure that is secured with Azure AD. A mobile app connects to this API using bearer tokens, works great. When I try calling the API from the browser, though, it returns a 401 because I'm not logged in. That's true because I'm not presented with a login screen.
My API doesn't have any UI so what I'd want it to do is to forward the user to Azure AD login and return to the API endpoint they were calling after authentication.
If I go to the Azure portal, there's a setting that says "Action to take when the request is not authorized". If I set that one to "Log in with Azure Active Directory", it behaves the way I want it to. But... I have some endpoints which need to be accessed anonymously, and this setting catches all requests, not caring about any [AllowAnonymous] attributes.
So any request to an endpoint labeled Authorize that is not authorized yet should be forwarded to Azure AD login, all others should be allowed.
Add a DelegatingHandler to your web api project and register it in WebApiConfig.cs:
config.MessageHandlers.Add(new UnAuthorizedDelegatehandler());
public class UnAuthorizedDelegatehandler: DelegatingHandler
There you can check for 401 status codes and do the redirect to whatever and also apply a redirect url as querystring parameter.
HttpResponseMessage rm = await base.SendAsync(request, cancellationToken);
if (rm.StatusCode == HttpStatusCode.Unauthorized)
{
// configure the redirect here
return rm;
}