I implemented the AzureB2C MVC Sample project into my solution so I could create a POC of its authentication services. The only issue is that I cant figure out how to authenticate users on my web project once the user is redirected back to us.
To elaborate, Project A contains this controller which authenticates the user -
public void SignUpSignIn()
{
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge();
return;
}
var username = "";
foreach (Claim claim in ClaimsPrincipal.Current.Claims)
{
if (claim.Type == "signInName")
{
username = "adtest3";
Session["username"] = username;
break;
}
}
Response.Redirect("https://SOMEWHERE IN PROJECT B/login/");
}
I'm able to access all claims without issue, but once the user is redirected to the login controller in PROJECT B, the claims are no longer accessible. First of all, how can I make them accessible? Why are they not accessible?
In general, we would use the OpenID connect middleware and the cookie authentication middleware for integrating Azure AD B2C with ASP.NET MVC application. At this point, the OpenID connect middleware would use the cookies as the authentication type, and the Claims encoded in the token you will receive from Azure AD B2C tenant will be stored in a Cookie. Moreover, you could follow the github code sample Azure AD B2C: Call an ASP.NET Web API from an ASP.NET Web App.
Based on your scenario, I assume that you could share cookie between your Project A (works as your custom authentication service) and Project B. If you share authentication cookie across multiple domains, you need to do some additional implementation. Details you could follow this blog.
I would prefer encode the Claims to a JWT token, then redirect to Project B, then you could decode the Claims and sign in the user with the Claims and redirect to the related page in your Project B.
Related
After looking at many code-sites and tryed out code sampels and ideas, I can't find a working way for my situation: I just want my old webforms app to get Azure AD sign in possibilities.
The old webapp is still selling very well so plan is to extend it.
Situation:
I have an classic Webforms solution on Framework 4.5.
Authentication mode="Forms".
I have a simple and custom membership provider.
Simple custom user table with scrambled passwords.
No MVC app, no controllers. Just plain old Global.asax, webcontrols and so.
Many users are in a tenant on a Azure AD. Or Office365 users. I want them to log on to my app.
ACS and AzMan are gone.
Now, in what way can I add Azure AD sign in feature?
Code tips, code examples?
I have seen texts and code samples for MVC apps and newer types.
Seen how to register my app in Azure AD, create a client secret, note the App ID, tenant ID and so. But no luck getting a working logon.
Some links read many times:
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-aspnet-webapp
and
Section "Quickstart Guides. Build a simple app to sign-in with user’s or app’s identity and call Microsoft Graph API in a few steps" on https://portal.azure.com/
According to your description, I suggest you could follow below steps to implement azure AD login in asp.net web form.
1.Add the code in Startup.cs.
public void Configuration(IAppBuilder app)
{ app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = "7d68201b-xxxxxx",
Authority = "https://login.microsoftonline.com/e4c9ab4e-xxxxxx"
});
}
2.Force a user to sign in by requesting an authentication challenge in your controller:
protected void Login_Click(object sender, EventArgs e)
{
Context.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
3.Add button click for login.
<div>
<asp:Button ID="Login" runat="server" Text="Login" OnClick="Login_Click" />
</div>
4.Add Redirect Url of your project url and click Implicit grant of Id token in app registration app in azure ad.
Have check authenticated user by using following code when we come back after
I am not able to comment but I think this is the way how we can check authenticated user when we come back and by login by Azure username/Password.
if (User.Identity.IsAuthenticated == true)
{
string Email = User.Identity.Name;
}
I have an API running using Azure AD authentication, with three roles (Admin/Manager/Viewer). On the API side of things, this all works fine, when a request comes in, the roles are all set correctly.
Now I'm building a website that communicates with this API (Currently Blazor server side, but could just as easily be an MVC site). The user logs into this site, and when they perform an action I'm using the On-Behalf-Of flow to acquire a token and call the API.
What is the best way for the website to know what roles the user has on the API? This would be used to hide/disable certain pages.
I see two ways right now:
Duplicate the roles so the web app has the same roles setup, worst case if the web app is missing one, they'll just get an error when executing a protected action
Expose an method on the api to return the users roles from the token and have the web app call this when a user logs in
Am I missing something here?
I figured out a way to do this, once the user logs in, I can acquire an access token for the api and then use the JwtSecurityTokenHandler to read it into a JwtToken and access the claims there.
var accessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUser(this._contextAccessor.HttpContext, new[] { _scope });
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(accessToken);
//jwt.Claims - get roles from claims
For serveral days now I am trying to get OAuth authentication with Google and Facebook to work within my ASP.net core web api project.
my current status is:
I have an ASP.net core Web Api project in which the users need to be authenticated
I have an angular 2 web app which should use my web api (with authentication)
I have an android app, which should use my web api (with authentication)
my goal is:
Using Google/Facebook as OAuth providers for login
later: adding own user accounts (probably with IdentityServer4)
no need to redirect to a special login website (like the IdentityServer4 solution). Just hit the facebook/google button in the app, allow access, done!
In my android and angular app I am able to retrieve the access tokens from google/facebook. Now, I want to use the OAuth implicit flow, to authenticate the user on my web api, with the given access tokens (putting the tokens into the header as bearer token)
There is my problem: is there any genric way to do this easily? I do not want to use the facebook/google SDKs for this.
I have tried following:
using IdentityServer4: With this I am able to login with facebook/google on my webapi, but there is need of a redirection to the IdentityServer4 login page. Is there any possible way of just hitting the google/fb-Button in my app and logging in, without redirection to the identityServer login page?
using the google/facebook authentication middleware (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/): But they are not validating my sent bearer token (tried countless ways to achieve proper validation). Is this even possible to use within the web api?
trying to use Microsoft.AspNetCore.Authentication.JwtBearer-Middleware and putting in the necessary options for google/facebook by myself, but also not validating (aswell countless attempts)
In the last few days, I have tried so much possible solutions, that I am totally stuck and lost track of what I need to do to achieve this. At this point I have read nearly every asp.net web api oauth tutorial/stackoverflow entry but can't figure out how to use this in my case as I want. Most tutorials are just for mvc-Websites or using IdentityServer4 with the redirection to its login page.
Any suggestions or solutions? What am I missing?
If I undertsand correctly, you already have your Facebook user token from Facebook SDK through your app.
Like you I couldn't find how to do it with an ASP.NET Core library / package. So I went back to basics.
I just call a endpoint of my api with the Facebook token, check it against the Facebook graph api and if fine then I register the user (if required) and return my JWT token as if the user logged through a classical username / password path.
[HttpPost]
[AllowAnonymous]
[Route("api/authentication/FacebookLogin")]
public async Task<IActionResult> FacebookLogin([FromBody] FacebookToken facebookToken)
{
//check token
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
var response = await httpClient.GetAsync($"me?access_token={facebookToken.Token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
if (!response.IsSuccessStatusCode) return BadRequest();
var result = await response.Content.ReadAsStringAsync();
var facebookAccount = JsonConvert.DeserializeObject<FacebookAccount>(result);
//register if required
var facebookUser = _context.FacebookUsers.SingleOrDefault(x => x.Id == facebookAccount.Id);
if (facebookUser == null)
{
var user = new ApplicationUser {UserName = facebookAccount.Name, Email = facebookAccount.Email};
var result2 = await _userManager.CreateAsync(user);
if (!result2.Succeeded) return BadRequest();
facebookUser = new FacebookUser {Id = facebookAccount.Id, UserId = user.Id};
_context.FacebookUsers.Add(facebookUser);
_context.SaveChanges();
}
//send bearer token
return Ok(GetToken(facebookUser.UserId));
}
You have to copy the custom code available in this article on medium
Creat a function in AccountController.cs
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
And paste the code given in the article
Can anyone point me to some good documentation or provide good information on the best way to implement authentication and authorisation for an ASP.NET Core REST API.I need to authenticating and authorising the app first and then authenticate and authorise the user.
Ideally I want to be able restrict the controller method that an authenticated app and/or user can access.
I am thinking of using AspNet.Security.OpenIdConnect.Serverenter for the App authentication but I am not sure then how best to perform the user authentication. Maybe reuse the OpenIdConnect authentication on a different endpoint for users with a different header to contain the user token.
Once authenticated I am thinking of just using roles base security to restrict which controllers methods can be accessed.
Is this the correct route to solving this problem?
This is actually a tougher question that that it may seem because the type of clients (software clients) that are using the api seem to drive what kind of auth* is needed. For example, in a web application, where the web application needs auth*, then Asp.Net Identity would work with either a token or a cookie. However, if other clients are going to consume the provided services (mobile apps, WUP apps, then it may be easier to implement using token authentication . When I had this problem, I ran into the issue that I had a knowledge gap because I didn't really understand OAuth. I had to get back to basics.
https://alexbilbie.com/guide-to-oauth-2-grants/
https://www.pluralsight.com/courses/oauth2-json-web-tokens-openid-connect-introduction
Most of the tutorials around Asp.Net Identity "Seem" to be geared towards web clients. Although it is possible to find those that are not. With the introduction of asp.net core, the syntax has changed and many of the old tutorials that show combining cookie and token authentication are no longer applicable. Additionally, Web Api is not longer a separated from other project types in Visual Studio making the change even more pronounced. Here are some older tutorials.
http://satvasolutions.com/combine-asp-net-identity-web-api-and-mvc-best-in-a-single-web-app/
http://blog.iteedee.com/2014/03/asp-net-identity-2-0-cookie-token-authentication/
Combine the use of authentication both for MVC pages and for Web API pages?
IdentityServer is a completely valid solution, works with both client credential and Resource owner credentials grant (user,password) and Brock Allen has usually been very responsive in SO under the tag
https://stackoverflow.com/questions/tagged/identityserver4
or on the github site under issues labeled as questions
https://github.com/IdentityServer/IdentityServer4/issues
With identity server, Once again, I had to go back to basics and work through the tutorials to get an understanding of how this would work in my project.
https://identityserver4.readthedocs.io/en/release/intro/big_picture.html
As Brock quickly pointed out to me in another post, asp.net ef identity is a user store and good to use with the resource owner credentials workflow.
For authentication you can use ASP.NET Core Identity that will use the Microsoft.AspNetCore.Identity.EntityFrameworkCore package, which will persist the identity data and schema to SQL Server using Entity Framework Core.
For authorization you can use Role Based Authorization that uses the Microsoft.AspNetCore.Authorization package.
You can also checkout this video for an overview on ASP.NET Core Authorization
I couldn't find any good documentation on this, however I had to achieve the same thing so I coded the rest api myself by modifying the actions in the standard ASP.NET authentication template to REST API equivalents.
For example here is how I worked the login action:
// POST: /Account/Login
[HttpPost("[action]")]
[AllowAnonymous]
public async Task<ReturnValue<ApplicationUser>> Login([FromBody] loginModel login)
{
if (ModelState.IsValid)
{
ApplicationUser user = await _userManager.FindByEmailAsync(login.email);
if (user == null)
{
return new ReturnValue<ApplicationUser>(false, "Login failed, check username and password.", null);
}
// else if (user.EmailConfirmed == false)
// {
// return new ReturnValue<ApplicationUser>(true, "Confirm email address.", null, user);
// }
else
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(user, login.password, (bool)login.rememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return new ReturnValue<ApplicationUser>(true, user);
}
//if (result.RequiresTwoFactor)
//{
// return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
//}
if (result.IsLockedOut)
{
return new ReturnValue<ApplicationUser>(false, "The account is locked out.", null);
}
}
}
else
{
string message = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));
return new ReturnValue<ApplicationUser>(false, "Invalid login attempt: " + message, null);
}
// If we got this far, something failed in the model.
return new ReturnValue<ApplicationUser>(false, "Login failed.", null);
}
If you call the API from a javascript within a browser the cookies will be loaded and you should be able to make further authorised calls to the API, if you're calling from another type of client, you will want to ensure the CookieContainer is retained for authorized calls.
From this point you can authorize your REST API controllers using [Authorize] decorator through the standard Microsoft libraries: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
Good luck.
Here it is:
A workshop for moving through the various new pieces in ASP.NET Core Authorization:
https://blogs.msdn.microsoft.com/webdev/2016/03/15/get-started-with-asp-net-core-authorization-part-1-of-2/
https://github.com/blowdart/AspNetAuthorizationWorkshop
Please refer following links.
For Asp.net Core
https://stormpath.com/blog/token-authentication-asp-net-core
For API
https://stormpath.com/blog/rest-api-mobile-dotnet-core
Assuming that I currently have a newly created project based on Visual Studio 2015 "WebApp" template with Individual Accounts authentication, I use Microsoft.AspNet.Authentication package and I can't always rely on cookies, because my web API should also target mobile apps:
How can I add authentication to my web API? I'm especially interested in token based authentication.
You can use basic http authentication or implement a similar one with a token or ticket passed through http headers.
Implement custom AuthorizeAttribute in your web api project. In IsAuthorized(HttpActionContext actionContext) overload you can check the authorization scheme and authorization header and then you can connect to your sessions provider and check if the user has an active session.
You must pass the login token in the authorization header, so if the token is missing that means there is no active user.
So when you login you must create and encrypt the token on successful login. Then pass this token with each request to the server.
This blog contains more information about using AuthorizeAttribute: http://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way
You can make separate table in db for storing authentication detail (AuthKey, UserID, CreatedDate, ExpiredDate, IsExpired) and make functions like CheckAuthorizationKey(string authKey), ExtendAuthorization(string authKey), ExpireAuthorization(string authKey){}
and call that functions for checking the authorization as below sample code.
public ServiceResult<LoginModel> Login(string auth_key)
{
var service = new ServiceResult<LoginModel>();
LoginModel user = new LoginModel();
if (AuthKey.CheckAuthorizationKey(auth_key) == false)
{
service.message = TemplateCodes.GetMessage(TemplateCodes.UnAuthorize, null, db);
service.status = ServiceStatus.authorization_failed;
return service;
}