Cannot understand MVC5 + WebApi2 Authorization - asp.net-web-api

I know what is the concept of OAuth: User sends request to the server with grant type, username and password, after some checks on server, the user receives an access token.
What I cannot understand is why I should do this:
ClaimsIdentity oAuthIdentity = await _userManager.CreateIdentityAsync(user,
context.Options.AuthenticationType);
var ticket = new AuthenticationTicket(oAuthIdentity, GenerareProperties(user));
context.Validated(ticket);
What is CreateIdentityAsync returning? What is an AuthenticationTicket? What does context.Validated do?
Also, If I have oAuthIdentity why should I also use cookiesIdentity? And finally, where is the access token being generated?
I searched but cannot find a website that explains this.

CreateIdentityAsync Will return the ClaimsIdentity to be used in the ClaimsPrincipal of the running context, which is further abstracted in...
An AuthenticationTicket is just a packaging of exactly what is passed in, for convenience.
context.Validated will add the information in the ticket to the current principal, and allow the OWIN pipeline to continue instead of returning a 401.
The reason for the cookiesIdentity is to allow authentication from the MVC pages in the template. It really is not used for the WebApi.
Some Sources for further reading:
Here is a nice article that describes the template from the RC, which was similar
Also here are two blogs where their authors break down parts of .NET security that might seem obscure

Related

MVC Prompt Query Parameter

I want to override Azure AD SSO login for a MVC web application. I don't want to log other applications out in the process, but require login for security purposes. I am using OAuth2.0 with OIDC via Owin for authentication.
I am trying to use the prompt=login query parameter, which should theoretically do the trick. I found a Github reference to this being recently made available in Core but cannot trace how to do it in MVC5.2
Is it possible to do it in the Application Builder? I tried adding .WithExtraQueryParameters ("prompt=login") to the ConfidentialClientApplicationBuilder when getting the access code. No luck.
Is there another workaround if the code doesn't come out-of-the-box?
EDIT: PublicClientApplication allows .WithPrompt(Prompt.Login) while ConfidentialClientApplication does not (also does not allow AcquireTokenInteractive) This is a web app so it needs the confidential builder. Tested using the Public builder and it logs in successfully. But I get an ActiveX instantiation error 'not in a single-threaded apartment'(?) Strange, unless that is how the token is being delivered perhaps. I also tested by changing to multitenant in Azure and by toggling Public client on and off.
Any ideas?
You could use ForceLogin to add paramter to ConfidentialClientApplicationBuilder.
ForceLogin: enables the application developer to have the user prompted for credentials by the service even if this would not be needed. This can be useful if Acquiring a token fails, to let the user re-sign-in. This is done by sending prompt=login to the identity provider. Again, we've seen it used in some security focused applications where the organization governance demands that the user re-logs-in each time they access specific parts of an application.
So, use the code as below:
result = await app.AcquireTokenInteractive(scopes)
.WithPrompt(Prompt.ForceLogin)
.ExecuteAsync();
The Modifier .WithExtraQueryParameters will not help you. You need to use .WithPrompt instead.Please refer article.
Example:
await PublicClientApplication
.AcquireTokenInteractive(scopes, null)
.WithAccount(CurrentUser)
.WithPrompt(Prompt.ForceLogin) // use login for your case
.ExecuteAsync();
I eventually resolved this as follows:
Under Notifications in the ConfigureAuth(IAppBuilder app) add a reference to a new task:
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
Then add the task:
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification
<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
// Forces the user to login.
if (notification.ProtocolMessage.Prompt == null)
{
notification.ProtocolMessage.Prompt = "login";
}
return Task.FromResult(0);
}
Hope that helps the next person with this issue.

How to integrate the new AD B2C and the C# Azure Mobile Client lib?

I have secured my API app and I have successfully tested my ADB2C flow with the sample app I found here: https://github.com/Azure-Samples/active-directory-b2c-xamarin-native. Using that structure, I can trigger the sign-in process, and then access my protected API calls.
However I wanted to also use the WindowsAzure.Mobile sdk as a convenience. It is hinted at here: https://cgillum.tech/2016/08/10/app-service-auth-and-azure-ad-b2c-part-2/ that you can trigger the B2C flow from LoginAsync in that class but it does nothing when I call it in that way.
I also found https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-dotnet-how-to-use-client-library/ (scroll to "Authenticate users with the Active Directory Authentication Library") where I substituted the MSAL calls for getting the token. This triggers the sign-on flow, I get a good token and claims back, then I put it in some JSON and pass it like so:
AuthenticationResult ar = await App.PCApplication.AcquireTokenSilentAsync(App.Scopes, "", App.Authority, App.SignUpSignInpolicy, false);
JObject payload = new JObject();
payload["access_token"] = ar.AccessToken;
user = await App.MobileService.LoginAsync(
MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
This call to LoginAsync throws
{Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: You do not have permission to view this directory or page.
at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient+<ThrowInvalidResponse>d__18.MoveNext () [0x0022f] in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
(snip)
Are they not designed to work together? Are those different kinds of tokens? The reason I'm using B2C is because I really don't WANT to know all that OAUTH stuff :)
In the case of B2C, you are actually getting back an ID token instead of an access token, and I believe the ar.AccessToken property would be null. This property also seems to go away in the latest versions of MSAL.
I suspect you just need to update the payload to "authenticationToken" and instead use ar.IdToken.
I am not sure if you can continue to use the "access_token" key in the payload, but it may be that you can. If not, try "authenticationToken" instead.

Missing Claims and Identity Info with IdentityServer v3

I have IdentityServer with Membership Reboot and IdentityManager running on a remote server, I've used the Admin UI of IdentityManager to setup a user, and add roles & claims to said user.
I'm developing a WebApi/SPA project that will use the remote server for Auth. Using fiddler I can request a token from the IdentityManagner on the remote box and use this token to against the local WebApi where Authorization is required. If the token is valid the WebApi processes like normal, if the token is bogus I get a 401. Works great.
The problem is when I want additional information about the user none of the claims or identity information is coming across. I'm not sure if the problem is at the IdentityServer side, The WebApi side, or if I'm not doing something correctly when getting my token.
I didn't realize we needed put the claims in the Scope definition. Incase anyone else stumbles upon this I changed my scope to the following
var scopes = new List<Scope>
{
new Scope
{
Enabled = true,
Name = "publicApi",
Description = "Access to our public API",
Type = ScopeType.Resource,
IncludeAllClaimsForUser = true, //I'll filter this down later
}
};
scopes.AddRange(StandardScopes.All);
return scopes;
Further details can be found here

ASP.net Web API RESTful web service + Basic authentication

I'm implementing a RESTful web service using ASP.Net Web Api. I have concluded to use Basic authentication + SSL to do the authentication part. What is the best/correct way to implement that?
My first attempt was to do it manually, parsing the Authorization header, decoding and verifying the user against my database. It works, but I wonder if I am missing something.
I've seen some solutions using user roles and principals. While I'm not sure what these actually do, I'm almost sure I will not be needing these, since in my database I define my own users and their roles.
Also what I haven't yet completely understand, is if the consumers of the service must sent the credentials with each request or they are somehow cached. Should my service do something in order for this to happen, or it's completely up to the consumer to handle this?
And a last question about clients making requests with javascript. Would there be any "cross domain request" problems if they try to use the service?
Jamie Kurtze provides a good explanation of using Basic Authentication here ASP.NET Web API REST Security Basics
From my understanding, if you want your requests to be stateless then each request will require the Authentication field to be set
Jamie Kurtze wraps the necessary code in a class derived from DelegateHandler, while Rick Strahl checks if the call is valid using a Filter. You can read more at his blog post on this topic at A WebAPI Basic Authentication Authorization Filter
Use basic authentication for the initial (sign in) request by adding a [BasicHttpAuthorize] attribute to the appropriate controllers/methods. Specify the Users and Roles with the attribute if desired. Define BasicHttpAuthorizeAttribute as a specialized AuthorizeAttribute like this:
public class BasicHttpAuthorizeAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (Thread.CurrentPrincipal.Identity.Name.Length == 0) { // If an identity has not already been established by other means:
AuthenticationHeaderValue auth = actionContext.Request.Headers.Authorization;
if (string.Compare(auth.Scheme, "Basic", StringComparison.OrdinalIgnoreCase) == 0) {
string credentials = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(auth.Parameter));
int separatorIndex = credentials.IndexOf(':');
if (separatorIndex >= 0) {
string userName = credentials.Substring(0, separatorIndex);
string password = credentials.Substring(separatorIndex + 1);
if (Membership.ValidateUser(userName, password))
Thread.CurrentPrincipal = actionContext.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity(userName, "Basic"), System.Web.Security.Roles.Provider.GetRolesForUser(userName));
}
}
}
return base.IsAuthorized(actionContext);
}
}
Have the initial response include an API key for the user. Use the API key for subsequent calls. That way, the client's authentication remains valid even if the user changes username or password. However, when changing password, give the user an option to "disconnect clients", which you implement by deleting the API key on the server.
Have a look here for a good basic authentication implementation
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
there is more to read about it at:
https://github.com/thinktecture/Thinktecture.IdentityModel.45/wiki

Spring Social Twitter Oauth

I want to use spring social to develop an twitter app which will update status and upload photos.I am not able to understand how to do Oauth authentication using Spring social.All examples I saw talks about hardcoding the accesstoken which would work only for that particular user.I dont want to hardcode anything except the app keys.
Kindly some one explain me how to do Twitter Oauth using spring social.I went through the official documentation of spring framework but got confused when I saw the other examples..
Thanks
I saw talks about hardcoding the accesstoken which would work only for that particular user.I dont want to hardcode anything except the app keys.
"app keys" a.k.a. consumer { key, secret } pair authorizes your app to use Twitter APIs that do not require user authentication. Think about it as you app browsing a twitter website without being logged in. Hence you'd have an ability to search, get timelines, etc.. => read only.
In case you'd like to post something back, you'd have to make you app do that on behalf of a real Twitter account / user. Think about someone writing a Twitter client => it can be downloaded by many different users, hence it needs two things to function properly:
Be a registered Twitter application => have consumer { key, secret } pair
Be able to post tweets / images on behalf of the user => have access { token, secret } pair
In order to get that access { token, secret } pair, you'd have to have an "OK" from that user/account.
That is where OAuth comes in => it sends the user to the confirmation page, where he clicks "OK, I allow this app to post on my behalf". This "OK" then gets converted to the OAuthToken that your app can use.
If all you want is to post updates on behalf of yourself, then you need to approve your own Twitter app, and persist that OAuthToken to be used by your app.
Unfortunately Twitter does not yet support OAuth 2.0, hence you'd have to do more... You'd have to do OAuth 1.0a.
Spring Social documentation describes the OAuth 1.0a flow here, where you can see the flow visually.
On order to "code" this flow using Spring Social APIs, you should first request access {token, value} pair ( there is a convenience ConnectController for it btw ):
TwitterConnectionFactory connectionFactory =
new TwitterConnectionFactory( "consumerKey", "consumerSecret" );
OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuthToken requestToken = oauthOperations.fetchRequestToken( "https://my-callback-url", null );
String authorizeUrl = oauthOperations.buildAuthorizeUrl( requestToken, OAuth1Parameters.NONE );
response.sendRedirect( authorizeUrl );
And once it comes back (to your callback URL) you can use OAuth1Operations to get OAuthToken which is exactly that pair.
// upon receiving the callback from the provider:
OAuthToken accessToken = oauthOperations.exchangeForAccessToken(
new AuthorizedRequestToken(requestToken, oauthVerifier), null);
Now, as you have all you need, you have choices:
Create a TwitterTemplate from that OAuthToken:
String consumerKey = "..."; // The application's consumer key
String consumerSecret = "..."; // The application's consumer secret
String accessToken = accessToken.getValue();
String accessTokenSecret = accessToken.getSecret();
Twitter twitter = new TwitterTemplate( consumerKey, consumerSecret, accessToken, accessTokenSecret );
Create a Twitter Connection object
Connection<Twitter> connection = connectionFactory.createConnection( accessToken );
Once you get the Connection, you might want to persist it via ConnectionRepository as shown here, so you don't have to go through obtaining access token again.
Here is Connection API.
The previous answer is good, but is only part of the story...
There are at least 3 levels at which you may work with Spring Social: (1) Using the TwitterTemplate directly, in which case you'd need to obtain the access token and secret through some means of your own, (2) use OAuth1Template, perhaps through TwitterConnectionFactory as the previous answer showed, to get the access token and from that create the TwitterTemplate, in which case you'd have to handle the redirects and callbacks yourself or (3) use Spring Social's ConnectController to handle everything for you.
Using ConnectController involves the least amount of OAuth work on your part. You just configure the appropriate pieces in Spring and ConnectController takes care of the rest. See http://static.springsource.org/spring-social/docs/1.0.x/reference/html/connecting.html for details.
I encourage you to have a look at the Spring Social Showcase sample at https://github.com/SpringSource/spring-social-samples. It uses ConnectController to handle by Twitter and Facebook connections. And, of course, you're welcome to ask questions on the Spring Social forum at http://forum.springsource.org/forumdisplay.php?82-Social.

Resources