MVC with REST and client authentication - asp.net-mvc

I've got a working model of an MVC application working with Authentication (using Azure B2C). In order to authenticate my client, I need to add a 'Bearer' token to the header like so:
public async Task<string> GetValuesAsync()
{
var client = new HttpClient { BaseAddress = new Uri(this.serviceOptions.BaseUrl, UriKind.Absolute) };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer",
await this.GetAccessTokenAsync());
return await client.GetStringAsync("api/products");
}
I don't want to create a proxy for every CRUD operation I have and I want to use the Kendo UI products which have a pretty slick RESTful API. Is there some way to automatically add the bearer token to the header in every HTTP operation so I don't have to make proxies and can use a proper RESTful API?

Related

Which token should I use in my React app call backend API , which forward call to Graph API

In my React app I use OAuth 2.0 auth code grant for authentication , and use Graph APi to make most of the requests (I have an app registered in Azure AD). They work perfectly with the access token I received using MSAL2 Provider (toolkit).
Providers.globalProvider = new Msal2Provider({
clientId: config.clientId,
authority: config.authority,
redirectUri: config.redirectUri,
scopes: [
"openid",
"profile",
"Calendars.ReadWrite",
"Place.ReadWrite",
"Place.ReadWrite.All",
"User.Read",
"People.Read",
],
});
I get the access token with following function:
const getAccessToken = async () => {
let token;
if (Providers.globalProvider.state === ProviderState.SignedIn) {
token = await Providers.globalProvider.getAccessToken();
token = `Bearer ${token}`;
}
return token;
};
Recently I got another service to do but not directly to the Graph API but by our Backend who after some validation make a query to Graph API ( exactly its a room update call
https://graph.microsoft.com/v1.0/places/${roomId}
My service :
const updateRoom=async (roomId:string|undefined, room:Room):Promise<void>=> {
return axios.put(`http://localhost:3000/api/v1/rooms/${roomId}`, {capacity:Number(room.capacity),equipments:room.tags},{
headers: {
Authorization: await getAccessToken(),
},
})
But what I get from the server is status 500, AxiosError: Request failed with status code 500\n.
When testing our backend app in Swagger- > it works , the room is updated correctly. I have tried to copy the token from the Swagger and use the same in my React app--> also works , but I can not use for this purpose the access token I receive from MSAL2. Why does it happen? Where to find a solution either on the front or backend?
Are you using the same account to test request in Swagger and React app? As docs say only "work or school account" is supported for Place update. can it be an issue?
Firstly, you have a backend api which required to be called by your react client app. Then your backend api also required to call ms graph api to update the room. So I deduce this document matched your scenario.
Then I have a question here, how your backend web app to call the ms graph api? There are 2 possibilities, one is that it calls ms graph api on behalf the application-self, which should use client credential flow. Another one is that it calls ms graph api on behalf of the signed-in user which required to use on-behalf-of flow.
When using client credential flow, it's not necessary to set microsoft authentication for your backend app, it depends on yourself to add authentication or not. And if you called this api, then it doesn't support application type of api permissin, then you are impossible to use client credential flow here.
Let's focus on the first scenario. The whole progress should look like this: your react client app generate an access token and use it to call your backend api --> your backend api validate the token and try to call graph api on behalf of the signed in user. In this scenario, you should protect your backend api with Azure AD first, so that it can managed by Azure AD authorization. Then using On-behalf-flow allows you to generate another access token with the access token send from react client app and use it to call ms graph api.
I have a sample with asp.net core MVC(represent the client app) and and asp.net core web api. In my MVC project, I generate an access token for calling the api.
[Authorize]
public async Task<string> GetAsync() {
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "api://aad_client_id_exposing_api/Tiny.Read" });
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get,"https://localhost:7212/WeatherForecast")
{
Headers =
{
{ HeaderNames.Authorization, "Bearer "+ accessToken}
}
};
var httpClient = _httpClientFactory.CreateClient();
var response = await httpClient.SendAsync(httpRequestMessage);
var res = "";
if (response.StatusCode == HttpStatusCode.OK)
{
res = await response.Content.ReadAsStringAsync();
}
return "hello" + res;
}
Pls note the scope I used above, it's not for graph api, but an api permission which exposed by ourself, more details can be seen here.
Then this is my web api. In program.cs and appsettings.json, I have the following to protect my api with Azure AD, with the nuget package Microsoft.Identity.Web.MicrosoftGraph:
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("Graph"))
.AddInMemoryTokenCaches();
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "aad_client_app_id",
"ClientSecret": "client_secret",
"Domain": "tenant_name",
"TenantId": "tenant_id" // A guid (Tenant ID = Directory ID) or 'common' or 'organizations' or 'consumers'
//"Audience": "api://aad_app_client_id_which_exposed_api" //I used the same aad client app to expose api and consent api permission, so I can comment this line
},
"Graph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
},
And this is my web api controller:
namespace WebApi.Controllers
{
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
private readonly GraphServiceClient _graphServiceClient;
public WeatherForecastController(GraphServiceClient graphServiceClient)
{
_graphServiceClient = graphServiceClient;
}
[RequiredScope("Tiny.Read")]
[HttpGet]
public async Task<string> GetAsync()
{
var user = await _graphServiceClient.Me.Request().GetAsync();
var name = user.DisplayName;
return name;
//return "world";
}
}
}
And it worked for me. I'm afraid your issue happened for the scope you used in the client app, it should be the scope you exposed by yourself but not the one which is used for calling graph api.

A simple ASP .NET MVC API controller using roles

I wrote a web application using ASP .NET MVC and authorization system by default. I configured IdentityRole and input through external providers. Using the current database I have created my data context. Now I want to write a Xamarin.Android app and connect to my database, I want a simple API. But the feature that you want to access this API was only available to user with a certain role. The API is really very simple and therefore do not want to add to the draft WCF or WebAPI project. How to do it best?
First, you don't need a separate project to use Web Api; you can use both MVC and Web Api in the same project. For one off endpoints for things like in-site AJAX requests, just creating MVC actions that return JSON or XML would be fine, but if you're talking about a true API, even if it's fairly simplistic, I'd say go Web Api.
You'd protect your Web Api actions much the same as you would your MVC actions, using the [Authorize] attribute. If you need to restrict by role, you just pass a role(s) to that. However, the big difference here, especially if you're serving a mobile app, is that you'll need pass the authorization along with the request. That's generally accomplished using the Authorization header along with a bearer token. Basically, you would need to set up an endpoint that signs a user in and returns a token. Then, each subsequent request that needs authorization includes that token in the header.
I want to finish and to fully answer this question and close this topic. I've been searching for how to add the ability for a mobile client to connect to an existing site on ASP.NET MVC. In my search, I came across a great article Justin Hyland on March 2, 2014
In principle, everything in this article is well and clearly written, but I want to make a tiny contribution for clarity.
Under Setup WebAPIConfig stated that the need
added in the following code to the WebApiConfig Register method
But if we consider the case ASP.NET MVC we don't have such file. It's all very simple, you just need such a file to create the folder App_Start. The contents of the file can be left exactly as it is in the article.
To get rid of the bugs which will inevitably appear we need to install two nuget package: Microsoft.AspNet.WebApi and Microsoft.AspNet.WebApi.Owin.
Excellent! Now we can turn to the method to obtain the token and then adding the token to the query we can get the needed data closed by the attribute [Authorize].
A small remark. If You need to access a method which is closed for a specific role that to the Authenticate method from the article should add a few lines of code. Immediately after the line:
identity.AddClaim(new Claim(ClaimTypes.Name, user));
add the line:
identity.AddClaim(new Claim(ClaimTypes.Role, role));
where role you can get the following, for example:
var userIdentity = UserManager.FindAsync(user, password).Result;
var role = RoleManager.FindById(userIdentity.Roles.First().RoleId).Name;
User and password you have to send a request.
I also want to give an example of code which will send request and receive response. To not have to look for and immediately start coding.
async Task<string> GetToken(string userName, string password)
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>( "user", userName ),
new KeyValuePair<string, string> ( "password", password )
}
);
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.PostAsync(APP_PATH + "/Authenticate", content);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
async Task<string> GetUserInfo(string token)
{
using (var client = CreateClient(token))
{
var response = await client.GetAsync(APP_PATH + "/ValidateToken");
return await response.Content.ReadAsStringAsync();
}
}
HttpClient CreateClient(string accessToken = "")
{
var client = new HttpClient();
if (!string.IsNullOrWhiteSpace(accessToken))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
return client;
}
All have only to call the appropriate methods in the correct order. I hope that is useful to someone.
P.S.
If You create a new project in Visual Studio to get this functionality you just need to tick:

Combine the use of authentication both for MVC pages and for Web API pages?

I have an MVC 5 web application and can login with a Login.cshtml page and get a cookie and the login works fine. But, I would like to do a login with the Web API and then (maybe) set a cookie so that I am logged in for my MVC pages... (or login with the MVC login and then access the Web API) however the web api returns a bearer token and not a cookie token... so this doesn't work. Is there a way to combine the use of authentication both for my MVC pages and for my Web API pages?
UPDATE:
This isn't really a code issue, more of a conceptual issue.
Normal MVC web pages examine a cookie named, by default, ".AspNet.ApplicationCookie" to determine the requesters identity. This cookie is generated by calling ApplicationSignInManager.PasswordSignInAsync.
WebAPI calls, on the other hand, examine the requests headers for an item named Authorization... and uses that value to determine the requesters identity. This is returned from a WebAPI call to "/Token".
These are very different values. My website needs to use both MVC pages and WebAPI calls (to dynamically update those pages)... and both need to be authenticated to perform their tasks.
The only method I can think of is to actually authenticate twice... once with a WebAPI call and again with the Login post. (see my Answer below).
This seems very hacky... but I don't understand the authorization code enough to know if there is a more proper way of accomplishing this.
The best way to achieve this, is to have an authorization server (a Web API generating a token) and token consumption middle-ware in your MVC project. IdentityServer should help. However I have done it like this:
I built an authorization server using JWT with Web API and ASP.Net Identity as explained here.
Once you do that, your Web APIs startup.cs will look like this:
// Configures cookie auth for web apps and JWT for SPA,Mobile apps
private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
// Cookie for old school MVC application
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true, // JavaScript should use the Bearer
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/api/Account/Login"),
CookieName = "AuthCookie"
};
// Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
app.UseCookieAuthentication(cookieOptions);
OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(ConfigurationManager.AppSettings["JWTPath"])
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
You can find the CustomOAuthProvider and CustomJwtFormat classes here.
I wrote a consumption logic (i.e. middleware) in all my other APIs (Resource servers) that I wanted to secure using the same token. Since you want to consume the token generated by the Web API in your MVC project, after implementing the authorization server, you need to the following:
In your MVC app, add this in startup.cs:
public void Configuration(IAppBuilder app)
{
ConfigureOAuthTokenConsumption(app);
}
private void ConfigureOAuthTokenConsumption(IAppBuilder app)
{
var issuer = ConfigurationManager.AppSettings["AuthIssuer"];
string audienceid = ConfigurationManager.AppSettings["AudienceId"];
byte[] audiencesecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);
app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieName = "AuthCookie" , AuthenticationType=DefaultAuthenticationTypes.ApplicationCookie });
//// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Passive,
AuthenticationType = "JWT",
AllowedAudiences = new[] { audienceid },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, audiencesecret)
}
});
}
In your MVC controller, when you receive the token, de-serialize it and generate a cookie from the access token:
AccessClaims claimsToken = new AccessClaims();
claimsToken = JsonConvert.DeserializeObject<AccessClaims>(response.Content);
claimsToken.Cookie = response.Cookies[0].Value;
Request.Headers.Add("Authorization", "bearer " + claimsToken.access_token);
var ctx = Request.GetOwinContext();
var authenticateResult = await ctx.Authentication.AuthenticateAsync("JWT");
ctx.Authentication.SignOut("JWT");
var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(applicationCookieIdentity);
Generate a machine key and add it in web.config of your Web API and ASP.Net MVC site.
With this, a cookie will be created and the [Authorize] attribute in the MVC site and the Web API will honor this cookie.
P.S. I have done this with a Web API issuing JWT (Authorization server or Auth & resource server) and was able to consume it in an ASP.Net MVC website, SPA Site built in Angular, secure APIs built in python (resource server), spring (resource server) and an Android App.
Ugg... what I had to do was use the Login.cshtml form and override the submit... make an Ajax call to get the WebApi bearer token... and then do the form submit to get the actual MVC cookie. So, I'm actually making two login requests... one for the WebApi token and the other for the MVC cookie.
Seem pretty hacky to me... it would be nice if there was some way to sign in to MVC using the bearer token... or a call to the WebApi that would return me a cookie that I can use for normal MVC page requests.
If anyone has a better way I would love to hear it.
This is script code that I added to Login.cshtml:
$(document).ready(function () {
$('form:first').submit(function (e) {
e.preventDefault();
var $form = $(this);
var formData = $form.serializeObject(); // https://github.com/macek/jquery-serialize-object
formData.grant_type = "password";
$.ajax({
type: "POST",
url: '#Url.Content("~/Token")',
dataType: "json",
data: formData, // seems like the data must be in json format
success: function (data) {
sessionStorage.setItem('token', data.access_token);
$form.get(0).submit(); // do the actual page post now
},
error: function (textStatus, errorThrown) {
}
});
});
});
I assume what you're trying to do is have pages served by MVC have javascript that makes calls to Web API methods. If you're using ASP.NET Identity to handle authentication (which it looks like you're doing), then MVC should be using OAuth tokens that can be passed to Web API for authentication.
Here's a snippet from some javascript code that works for me in a similar situation:
var token = sessionStorage.getItem('access_token');
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: <GET/POSt/...>,
url: <your api>,
headers: headers
}).done(function (result, textStatus) {
I have similar case with you, but i use a different way to authenticate.
I have a web and an api, which all for intranet users. I do not use user's identity to pass web and api. Instead, i created a individual web account, and every time web will use this special account to connect to api.
Because, we also need to make sure that users should not connect to api directly. They should only connect to web ui.
Hope this help you.
From your comments above, from what I understand, you have a scenario wherein you perform login through browser but also have to invoke web-api methods using ajax calls.
The browser calls are session-cookie based. While the ajax calls from the browser would have the session cookie in the header, what is required is the authentication header to be present for the web-api to perform validation.
So on a successful login you'd also have to generate a web-api based token, set it as a cookie (that is accessible by javascript) and then while making ajax calls, pick it up from the cookie and include it as header in your 'Authorization' header.

How do I authorize access to ServiceStack resources using OAuth2 access tokens via DotNetOpenAuth?

I've created an OAuth2 authorization server using DotNetOpenAuth, which is working fine - I'm using the resource owner password flow, and successfully exchanging user credentials for an access token.
I now want to use that access token to retrieve data from secure endpoints in a ServiceStack API, and I can't work out how to do so. I've examined the Facebook, Google, etc. providers included with ServiceStack but it's not clear whether I should be following the same pattern or not.
What I'm trying to achieve (I think!) is
OAuth client (my app) asks resource owner ('Catherine Smith') for credentials
Client submits request to authorization server, receives an access token
Client requests a secure resource from the resource server (GET /users/csmith/photos)
The access token is included in an HTTP header, e.g. Authorization: Bearer 1234abcd...
The resource server decrypts the access token to verify the identity of the resource owner
The resource server checks that the resource owner has access to the requested resource
The resource server returns the resource to the client
Steps 1 and 2 are working, but I can't work out how to integrate the DotNetOpenAuth resource server code with the ServiceStack authorization framework.
Is there an example somewhere of how I would achieve this? I've found a similar StackOverflow post at How to build secured api using ServiceStack as resource server with OAuth2.0? but it isn't a complete solution and doesn't seem to use the ServiceStack authorization provider model.
EDIT: A little more detail. There's two different web apps in play here. One is the authentication/authorisation server - this doesn't host any customer data (i.e. no data API), but exposes the /oauth/token method that will accept a username/password and return an OAuth2 access token and refresh token, and also provides token-refresh capability. This is built on ASP.NET MVC because it's almost identical to the AuthorizationServer sample included with DotNetOpenAuth. This might be replaced later, but for now it's ASP.NET MVC.
For the actual data API, I'm using ServiceStack because I find it much better than WebAPI or MVC for exposing ReSTful data services.
So in the following example:
the Client is a desktop application running on a user's local machine, the Auth server is ASP.NET MVC + DotNetOpenAuth, and the Resource server is ServiceStack
The particular snippet of DotNetOpenAuth code that's required is:
// scopes is the specific OAuth2 scope associated with the current API call.
var scopes = new string[] { "some_scope", "some_other_scope" }
var analyzer = new StandardAccessTokenAnalyzer(authServerPublicKey, resourceServerPrivateKey);
var resourceServer = new DotNetOpenAuth.OAuth2.ResourceServer(analyzer);
var wrappedRequest = System.Web.HttpRequestWrapper(HttpContext.Current.Request);
var principal = resourceServer.GetPrincipal(wrappedRequest, scopes);
if (principal != null) {
// We've verified that the OAuth2 access token grants this principal
// access to the requested scope.
}
So, assuming I'm on the right track, what I need to do is to run that code somewhere in the ServiceStack request pipeline, to verify that the Authorization header in the API request represents a valid principal who has granted access to the requested scope.
I'm starting to think the most logical place to implement this is in a custom attribute that I use to decorate my ServiceStack service implementations:
using ServiceStack.ServiceInterface;
using SpotAuth.Common.ServiceModel;
namespace SpotAuth.ResourceServer.Services {
[RequireScope("hello")]
public class HelloService : Service {
public object Any(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
}
This approach would also allow specifying the scope(s) required for each service method. However, that seems to run rather contrary to the 'pluggable' principle behind OAuth2, and to the extensibility hooks built in to ServiceStack's AuthProvider model.
In other words - I'm worried I'm banging in a nail with a shoe because I can't find a hammer...
OK, after a lot of stepping through the various libraries with a debugger, I think you do it like this: https://github.com/dylanbeattie/OAuthStack
There's two key integration points. First, a custom filter attribute that's used on the server to decorate the resource endpoints that should be secured with OAuth2 authorization:
/// <summary>Restrict this service to clients with a valid OAuth2 access
/// token granting access to the specified scopes.</summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
public class RequireOAuth2ScopeAttribute : RequestFilterAttribute {
private readonly string[] oauth2Scopes;
public RequireOAuth2ScopeAttribute(params string[] oauth2Scopes) {
this.oauth2Scopes = oauth2Scopes;
}
public override void Execute(IHttpRequest request, IHttpResponse response, object requestDto) {
try {
var authServerKeys = AppHostBase.Instance.Container.ResolveNamed<ICryptoKeyPair>("authServer");
var dataServerKeys = AppHostBase.Instance.Container.ResolveNamed<ICryptoKeyPair>("dataServer");
var tokenAnalyzer = new StandardAccessTokenAnalyzer(authServerKeys.PublicSigningKey, dataServerKeys.PrivateEncryptionKey);
var oauth2ResourceServer = new DotNetOpenAuth.OAuth2.ResourceServer(tokenAnalyzer);
var wrappedRequest = new HttpRequestWrapper((HttpRequest)request.OriginalRequest);
HttpContext.Current.User = oauth2ResourceServer.GetPrincipal(wrappedRequest, oauth2Scopes);
} catch (ProtocolFaultResponseException x) {
// see the GitHub project for detailed error-handling code
throw;
}
}
}
Second, this is how you hook into the ServiceStack HTTP client pipeline and use DotNetOpenAuth to add the OAuth2 Authorization: Bearer {key} token to the outgoing request:
// Create the ServiceStack API client and the request DTO
var apiClient = new JsonServiceClient("http://api.mysite.com/");
var apiRequestDto = new Shortlists { Name = "dylan" };
// Wire up the ServiceStack client filter so that DotNetOpenAuth can
// add the authorization header before the request is sent
// to the API server
apiClient.LocalHttpWebRequestFilter = request => {
// This is the magic line that makes all the client-side magic work :)
ClientBase.AuthorizeRequest(request, accessTokenTextBox.Text);
}
// Send the API request and dump the response to our output TextBox
var helloResponseDto = apiClient.Get(apiRequestDto);
Console.WriteLine(helloResponseDto.Result);
Authorized requests will succeed; requests with a missing token, expired token or insufficient scope will raise a WebServiceException
This is still very much proof-of-concept stuff, but seems to work pretty well. I'd welcome feedback from anyone who knows ServiceStack or DotNetOpenAuth better than I do.
Update
On further reflection, your initial thought, to create a RequiredScope attribute would be a cleaner way to go. Adding it to the ServiceStack pipeline is as easy as adding the IHasRequestFilter interface, implementing a custom request filter, as documented here: https://github.com/ServiceStack/ServiceStack/wiki/Filter-attributes
public class RequireScopeAttribute : Attribute, IHasRequestFilter {
public void RequireScope(IHttpRequest req, IHttpResponse res, object requestDto)
{
//This code is executed before the service
//Close the request if user lacks required scope
}
...
}
Then decorate your DTO's or Services as you've outlined:
using ServiceStack.ServiceInterface;
using SpotAuth.Common.ServiceModel;
namespace SpotAuth.ResourceServer.Services {
[RequireScope("hello")]
public class HelloService : Service {
public object Any(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
}
Your RequireScope custom filter would be almost identical to ServiceStack's RequiredRoleAttribute implementation., so use it as a starting point to code from.
Alternately, you could map scope to permission. Then decorate your DTO or service accordingly (see SS wiki for details) for example:
[Authenticate]
[RequiredPermission("Hello")]
public class HelloService : Service {
public object Any(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
Normally ServiceStack calls the method bool HasPermission(string permission) in IAuthSession. This method checks if the list List Permissions in IAuthSession contains the required permission, so, in a custom IAuthSession you could override HasPermission and put your OAuth2 scopes checking there.

How to do ASP.NET Web API integration tests with authorize attribute

I do have authorize attribute applied on my Web API.
I am calling Web API from MVC4 application in which I am using standard cookie based authentication.
I need to call Web API method on controllers from integration tests but because authorize attribute is applied I will always receive unauthorized exception.
What is the best way to solve this problem ?
PS. I don't want (need) to use other methods of authentication such as APIKey,Token in Auth Header and similar...
First of all, one key element in order to answer this question is to know what kind of authentication mechanism you use. For example, if you use basic auth, you can send the credentials when you are integration testing:
[Fact]
public async Task FooTest() {
var username = "user";
var password = "supersecret";
// construct your config here as I do below.
// RouteConfig and WebAPIConfig are my own classes
var config = new HttpConfiguration();
RouteConfig.RegisterRoutes(config);
WebAPIConfig.Configure(config);
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/cars");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue(
"Basic", EncodeToBase64(string.Format("{0}:{1}", username, password)));
using (var httpServer = new HttpServer(config))
using (var client = new HttpClient(httpServer)) {
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsAsync<Car>();
// do you test now...
}
}
private static string EncodeToBase64(string value) {
byte[] toEncodeAsBytes = Encoding.UTF8.GetBytes(value);
return Convert.ToBase64String(toEncodeAsBytes);
}
Of course, your handler which handles the authentication should be able to authenticate you with those credentials.
On the other hand, as you will be hosting the application in memory, setting an authenticated principal to the Thread.CurrentPrincipal would be another option but wouldn't be my favorite option here.

Resources