I know this is very common question. But I really do not know how to integrate it.
I want to add authentication to my web api services. Right now I have created one console application to call service's method.
I have gone through this blog. I just want to implement authentication filter as mentioned in this article.
I want to know how can I pass credentials along with HTTPClient from my console application, fetch those things to web API and authenticate them.
I have created authentication filter but it does not invoke AuthenticateAsync method of authentication filter.
To pass http client I have done this:
public void GetData()
{
HttpClient cons = new HttpClient();
cons.BaseAddress = new Uri("http://localhost:50524/");
cons.DefaultRequestHeaders.Accept.Clear();
cons.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = Encoding.ASCII.GetBytes("Ankita:ankita123");
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(data));
cons.DefaultRequestHeaders.Authorization = header;
//MyAPIPost(cons).Wait();
MyAPIGet(cons).Wait();
}
Teaching you how to implement authentication in Web API will take a lot of time. You better stick to online tutorials.
The blog you've read tackles about different authentication for ASP.NET. Since you've tagged your question as ASP.NET Web API 2, I would suggest using a token-based authentication utilizing OWIN middleware. Check this out. The guide uses a console application for checking the requests to the web API.
The gist of it is...
Client > Token Provider (Generate token for valid user) > Web API > Check if Token is Valid (Existing and not expired) > Authenticate!
Considering you are trying to access the API with an HttpClient, you can pass it an instance of HttpClientHandler when creating it, which allows you to set the credentials that will be used when it performs requests:
new HttpClient(new HttpClientHandler { Credentials = new NetworkCredential(userName, password) })
Hope it helps!
I have successfully implemented authentication using this article. In that filter attribute is implemented.
Related
Edit:
Here is my question reformulated:
I have a web server with secured api endpoints - one must have been authenticated with Google prior to using them. I implemented Challenge and Callback endpoints for that.
This works well from a browser with my SPA web front-end. The user gets redirected to the Google website to sign-in and then gets redirected back to my webapp; the browser then has the authenticated cookies and the webapp can use the endpoints to update its state.
I also have a WPF application that will communicate with the web server.
I want the WPF application to do the same as the web front-end: Use the web api endpoints after being authenticated with Google. The connection between the WPF application and my web server is done through an HttpClient.
My problem is I don't know how to authenticate that HttpClient connection between the WPF app and the web server.
I tried using the same Challenge endpoint but the response I get is of course the HTML from the Google Sign-In page, so I guess I can't use that with an HttpClient...
I also tried authenticating with GoogleApis from the WPF app and use the authenticated token to set cookies in the HttpClient but apparently this is not compatible.
How to authenticate an HttpClient connection to a web api with an external provider such as Google?
Original question:
From a WPF application, the user authenticates with Google with this code:
using Google.Apis.Auth.OAuth2;
...
public void Authenticate()
{
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "myClientId",
ClientSecret = "myClientSecret"
},
new[] { "email", "openid" },
"user",
CancellationToken.None).Result;
}
This works and the UserCredential object contains the authenticated token:
How to embed this token information in a web request made with an HttpClient in order to call my webapi endpoint?
I think the request must include some cookies to inform the server that it has been authenticated, but I don't know which ones exactly.
The endpoint on the server-side validates that the user is authenticated with the help of IdentityServer:
var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
If I got your question right, you just have to set the Authorization header
var credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
clientSecrets,
new[] { "email", "openid" },
"user",
CancellationToken.None);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
credentials.Token.TokenType,
credentials.Token.IdToken);
Maybe you'll find below a helpful hint to better understand OpenID :)
The confusion stems from mixing GoogleApis and IdentityServer frameworks.
Authentication/authorization can be achieved using either of them.
Objects from Google.Apis.Auth.OAuth2 and IdentityServer4 namespaces are not designed to interact.
No manual cookie handling is necessary, for sure.
Ask yourself to whom does Google provide trust for the user. If it calls back to WPF, then webapi trusting WPF is a separate issue.
You answer your own question in the question:
the browser then has the authenticated cookies and the webapp can use
the endpoints to update its state
HttpClient needs to send those same cookies.
How do I set a cookie on HttpClient's HttpRequestMessage
If I understood your question right, then I faced the same problem not too long ago.
The way I implemented it is that in the backend, no matter who tries to access the endpoint, they had to send a Bearer X authorization token.
The token contained the identity of the client that wanted to access the resource, and I checked if he was permitted.
No matter what kind of client wants to access the endpoint, it just has to have that authroziation header in the request that he sends and the backend will treat it the same.
In my scenario, I used an authentication service that returns a cookie to the client with a certain JWT that contains the identity information.
Then from the client I send in every request the JWT received from the authentication service as an authorization header to the backend.
The reason I had to put the JWT that I receive from the service in a header, is that the authentication service and the backend service are not in the same domain, so cookies cant be shared.
This results in such design that no matter how you authenticate the client, the end result must be some sort of token that the backend can receive and read.
Hope this helps.
I want to implement a single sign on feature using my own API. Third party application(web application) will call this API and authenticate the users. For the communication between my API and other applications web request will be used. Below is the solution I provided for this,
I have created a API on my application and do the authentication based on request values. After successful authentication, I create the authentication cookie and add it to the response.
On the other app I used a HttpWebRequest and create CookieContainer. Then I get the cookies from response and assign those cookies to Response.
var response = (HttpWebResponse)http.GetResponse();
foreach (Cookie cook in response.Cookies)
{
Response.Cookies.Add(new System.Web.HttpCookie(cook.Name, cook.Value)
{
Domain = cook.Domain,
Expires = cook.Expires
});
}
In my test environment this works fine since both authentication API and other app are in same domain. But in customer testing phase this does not work due to domain mismatch. Because Authentication API is in different domain.
Is there any way to resolve this issue ?
I think it is impossible with cookies because they are domain bound and are not sent along with requests to domains. I guess you need see about other technology.
I hope this link will be useful
Good Luck
I am very new in implementing OAuth 2.0. I have implemented web-reference (ASMX file) in my xamarin project. Now I need to implement OAuth 2.0 for authentication. But I am not sure if ASMX supports OAuth2.0 or not. Do I need to implement WCF instead of Web refernce(ASMX) or is it possible in web reference (ASMX) to implement the OAuth2.0?
One possible solution is to add the token aquired from the authority to the Authorization header.
Your code could look similar to this:
var redirectURI = Windows.Security.Authentication.Web.WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
var _authContext = new AuthenticationContext(authority);
var tokenResult = await _authContext.AcquireTokenAsync(serviceResourceId, clientId, redirectURI);
if (tokenResult.Status != AuthenticationStatus.Success)
{
//Not authenticated
return;
}
var svc = new YourServiceReference.YourClient();
using (var scope = new OperationContextScope(svc.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = tokenResult.AccessToken;
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = svc.MyFunction();
//Do something with the data
}
Tricky - this is how mobile OAuth solutions work - but it is a big job:
Your Xamarin app would need to implement Mobile SSO to sign users in
Users of your Xamarin app would be redirected to login via an Authorization Server / Identity Provider after which they will receive an OAuth access token
After login your Xamarin App would then be able to call an API with the token and act on behalf of the user to get data
The API would need to validate received access tokens
SOLUTION PARTS
API: ASMX is an old technology so if you are working on the Microsoft stack you would use something newer such as a .Net Core Web API
MOBILE APP: The harder part of the solution will be implementing Mobile SSO, if you have not done so already.
How much of this solution exists already?
I have mvc5 application with custom login implementation. Once i got the credentials from user am making post and getting the token to validate the user. Owin Token implementation in separate class library project.
[HttpPost]
[AllowAnonymous]
public ActionResult Login(UserLoginViewModel model)
{
string baseAddress = "http://localhost:4312";
Token token = new Token();
using (var client = new HttpClient())
{
var form = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", "jignesh"},
{"password", "user123456"},
};
var tokenResponse = client.PostAsync(baseAddress + "/otoken", new FormUrlEncodedContent(form)).Result;
//var token = tokenResponse.Content.ReadAsStringAsync().Result;
token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result;
........
}
}
I am not sure how to make call /trigger the token implementation in class library project from mvc application. because class library project is not executable project. is it possible way of implementing token based implementation in separate class lib and make use of that implementation in different application (mvc and webapi).
my layer
UI(MVC) -> Authentication project (Owin class libarary) -> entity framework
any ideas?
Yes you can, but you need to expose your application login through an API of some sort.
For example you can create a token server which is responsible for authentication of both your API and you MVC project - an external provider - like Google or Facebook for example.
This is also the best way to share the same token between your two applications (MVC and API).
Check this article, it's extremely clear.
Hope it helps :)
For token based authentication, you need to use configure your mvc application or webapi to issue token. class library cannot issue token.The primary reason is that, you need to call the url configured to fetch the token eg.http://localhost:8080/api/gettoken.
So, either use webapi to issue token or mvc app to issue token.
I'm trying to create a simple proof of concept OAuth enabled application but am stuck on the authorization code implementation. Everywhere I read seems like it goes in one way or another, never actually using the authorization code flow. I've been using the following resources for information:
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-31
https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified
http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
I have setup web api and owin with a custom OAuthAuthorizationServerProvider to accept password grant types for refresh tokens and the ability to exchange a refresh token for an access token. This is working well, but I want to setup a scenario where I redirect a browser to the server to authorize and redirect back to the client with an authorization code. I then want the client to sent the authorization code to the token endpoint to get a refresh token
In the second link under Web Server Apps, I'm trying to get my web api app to surface an authorization code from a request like, http://127.0.0.1/auth?response_type=code&client_id=123&redirect_uri=http://validredirect.com&scope=access, but I keep getting a 404.
I've configured owin as follows:
var databaseContext = new AdnsfContext();
WebApp.Start(
new StartOptions("http://127.0.0.1:7000"),
appBuilder =>
{
var httpConfig = new HttpConfiguration();
httpConfig.MapHttpAttributeRoutes();
httpConfig.SuppressDefaultHostAuthentication();
httpConfig.Filters.Add(new HostAuthenticationFilter("Bearer"));
appBuilder
.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
ApplicationCanDisplayErrors = true,
AuthorizeEndpointPath = new PathString("/auth"),
TokenEndpointPath = new PathString("/token"),
AuthorizationCodeExpireTimeSpan = TimeSpan.FromMinutes(1),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(1),
Provider = new AuthServerProvider(),
AuthorizationCodeProvider = new AuthorizationCodeProvider(),
RefreshTokenProvider = new RefreshTokenProvider(),
})
.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
AuthenticationType = "Bearer",
})
.UseCors(CorsOptions.AllowAll)
.UseWebApi(httpConfig);
});
The pieces I've added to enable the authorization endpoint are the properties for the auth server options:
AuthorizeEndpointPath = new PathString("/auth"),
AuthorizationCodeExpireTimeSpan = TimeSpan.FromMinutes(1),
AuthorizationCodeProvider = new AuthorizationCodeProvider(),
The overrides in my implementation of the AuthorizationCodeProvider throw not implemented exceptions but it's currently not even hitting any breakpoints set in the code. One thing to note is that when I use postman to hit the auth endpoint, I get a server header back for HTTPAPI/2.0 which is different than if there simply isn't something surfaced at that endpoint, which means I must be sending the request incorrectly. Can anyone see a problem with my setup? Thanks in advance, I know that this is clearly my failing in understanding OWIN and OAuth.
One thing to note with the OAuth2 authorization server built in Katana is that it's transparent: you must provide your own /auth endpoint (using MVC or Nancy for instance) or directly render your consent form in OAuthAuthorizationServerProvider.AuthorizationEndpoint
You can take a look at https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Mvc for a complete sample. It doesn't use the OAuth2 authorization server built in Katana but a much more elaborated fork targeting OpenID Connect but you should get the idea.
Take a look at IdentityServer. It's based on Owin.
There is also samples repository where you can find a lot of examples using selfdeployed and\or 3rd party identity providers.
I think that this one example is most appropriate for you.