I'm new to ServiceStack and using it to provide an endpoint that will receive incoming requests from a remote service. No end user is involved.
The authentication flow goes like this (as specified by the author of the remote service):
"Their" remote service calls "our" endpoint, with JWT in header
"Our" endpoint extracts the 'kid' from the JWT
"Our" endpoint calls "their" oauth endpoint, with 'kid' as parameter
"Their" oauth endpoint returns a public key in form of a JWK (RS256)
"Our" endpoint verifies the JWT signature using the JWK
Does ServiceStack support this authentication flow?
I think I need to write code that hooks into the request's authentication and does steps 2-5 above. Is that right?
Edit:
I found this answer which looks to be what I'm after, i.e. custom AuthProvider that overrides PreAuthenticate with steps 2-5 above.
using System;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Web;
namespace MyService
{
public class CustomJwtAuthProvider : AuthProvider, IAuthWithRequest
{
public CustomJwtAuthProvider ()
{
Provider = "CustomJwtAuthProvider";
AuthRealm = "/auth/CustomJwtAuthProvider";
}
public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
{
return session.IsAuthenticated;
}
public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
{
throw new NotImplementedException("Authenticate() should not be called directly");
}
public void PreAuthenticate(IRequest req, IResponse res)
{
// Get kid from JWT
// Get public JWK from oauth endpoint
// Verify JWT signature using JWK
if ( /* JWT sig verified */ )
{
req.Items[Keywords.Session] = new AuthUserSession
{
IsAuthenticated = true,
};
}
}
}
}
Then in the ApplicationHost.Configure():
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new CustomJwtAuthProvider(),
}));
Does this approach seem right? Do I need to hand-roll the JWT authentication, or can I leverage ServiceStack's built in features and plugins more?
For them to be able to send you a JWT that ServiceStack accepts as an Authenticated Request, your App would need to be configured with either their AES Key if they're using HMAC-SHA* algorithm or their public RSA key if they're using JWE.
This flow is very strange, for them to be able to send you a custom JWT Key they would need to be able to craft their own JWT Key which means they need either the AES or private RSA Key your App is configured with where they'd be the only ones you will be able to authenticate with your App via JWT?
It's very unlikely that you'll want to configuring your App with that of a remote Service, instead you should probably use a JWT library like the JWT NuGet Package to just verify the JWT they send you is from them, then extract the KID, call their endpoint and validate the JWK they send you using a .NET library like JWK to verify their key.
Note this flow is independent from ServiceStack's JWT Support which you would use to enable stateless authentication to your Services via JWT. Here you're just using JWT and JWK libraries to verify their keys and extract required info from them.
Related
I was working on getting a client credential flow with Auth0 to work using Spring Security 5.4.1. I created a little demo application for reference: https://github.com/mathias-ewald/spring-security-auth0-clientcredentials-demo
Everything works fine, but I was wondering how to handle multiple OAuth2 clients. As far as I understand, the configuration made in OAuth2ClientSecurityConfig is valid for all client credential flows to any provider, correct?
What if I have another provider and don't want to convert RequestEntity in the same way?
There's usually no perfect answer for multi-tenancy since a lot depends on how early in the request you want to fork the behavior.
In Spring Security's OAuth 2.0 Client support, the ClientRegistration is the tenant, and that tenant information is available in most of the client APIs.
For example, your Auth0RequestEntityConverter could have different behavior based on the ClientRegistration in the request:
public RequestEntity<?> convert(
OAuth2ClientCredentialsGrantRequest request) {
ClientRegistration client = request.getClientRegistration();
if (client ...) {
} else if (client ...) {
} ...
}
Or, if you need to configure more things than the request entity converter, you could instead fork the behavior earlier by constructing a OAuth2AuthorizedClientManager for each provider:
public class ClientsOAuth2AuthorizedClientManager implements OAuth2AuthorizedClientManager {
private final Map<String, OAuth2AuthorizedClientManager> managers;
// ...
public OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest request) {
String clientRegistrationId = request.getClientRegistrationId();
return this.managers.get(clientRegistrationId).authorize(request);
}
}
I have two apis written in .NET Core and targeting 4.6.1:
myAuthApi (http://localhost:8496): which verifies credentials and issues tokens to clients. It also has an endpoint /api/values/1 (with an Authorize attribute on this action, used to validate tokens)
myPublicApi(http://localhost:8497): which receives tokens from the client on /api/values/1 (with an Authorize attribute on this action, also used to validate tokens). myPublicApi does not have any tokens endpoint and is meant to be a resource server.
I am using AspNet.Security.OpenIdConnect.Server 1.0.0.
Both APIs are Service.Fabric Stateless Services
I can successfully get the token with the following request format to http://localhost:8496/connect/token
client_id=XX&client_secret=XXX&grant_type=password&username=XXX&password=XXX
When validating the token against myAuthApi (http://localhost:8496/api/values/1) it works. However, when using that same token against myPublicApi(http://localhost:8497/api/values/1) it does not.
In both APIs, in the Startup.cs, I have
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Connect to Redis database.
var redis = ConnectionMultiplexer.Connect(ConnectionHelper.GetRedisConnectionString(Configuration));
services.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys")
.ProtectKeysWithCertificate(CertificateHandler.GetX509Certificate2(Configuration));
// Add framework services.
services.AddMvc().AddJsonOptions(opts =>
{
// we set the json serializer to follow camelCaseConventions when
// receiving /replying to JSON requests
opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
// we add authentication for the oAuth middleware to be registered in the DI container
services.AddAuthentication();
}
In myPublicApi I have:
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Add a new middleware validating access tokens.
app.UseOAuthValidation(options =>
{
// Automatic authentication must be enabled
// for SignalR to receive the access token.
options.AutomaticAuthenticate = true;
options.Events = new OAuthValidationEvents
{
// Note: for SignalR connections, the default Authorization header does not work,
// because the WebSockets JS API doesn't allow setting custom parameters.
// To work around this limitation, the access token is retrieved from the query string.
OnRetrieveToken = context =>
{
// Note: when the token is missing from the query string,
// context.Token is null and the JWT bearer middleware will
// automatically try to retrieve it from the Authorization header.
context.Token = context.Request.Query["access_token"];
return Task.FromResult(0);
}
};
});
app.UseMvc();
}
In myAuthApi I have:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Add a new middleware validating access tokens.
app.UseOAuthValidation(options =>
{
// Automatic authentication must be enabled
// for SignalR to receive the access token.
options.AutomaticAuthenticate = true;
options.Events = new OAuthValidationEvents
{
// Note: for SignalR connections, the default Authorization header does not work,
// because the WebSockets JS API doesn't allow setting custom parameters.
// To work around this limitation, the access token is retrieved from the query string.
OnRetrieveToken = context =>
{
// Note: when the token is missing from the query string,
// context.Token is null and the JWT bearer middleware will
// automatically try to retrieve it from the Authorization header.
context.Token = context.Request.Query["access_token"];
return Task.FromResult(0);
}
};
});
// Add a new middleware issuing access tokens.
app.UseOpenIdConnectServer(options =>
{
options.Provider = new AuthenticationProvider();
// Enable the logout, token and userinfo endpoints.
options.LogoutEndpointPath = "/connect/logout";
options.TokenEndpointPath = "/connect/token";
options.UserinfoEndpointPath = "/connect/userinfo";
CertificateHandler.SetupCommonAuthServerOptions(options, Configuration);
});
app.UseMvc();
}
As you can see, my data protection provider is storing keys in Redis, and I am protecting keys with a certificate which I am sharing across the 2 applications.
The resource server does not have any authentication provider configured and does not have UseOpenIdConnectServer in startup. In asp.net Web API 2, the token decryption used to be managed across the apps using shared machine keys.
How can I successfully validate the token issued by myAuthApi across all other apps using oAuthValidation?
EDIT, some logs can be seen here:
https://pastebin.com/ACDz1fam
EDIT2 :
After reading the logs thoroughly, I saw that the unprotection of the token was using the same Data Protection Provider, but different purposes:
"Performing unprotect operation to key {4406cfa7-a588-44ba-b73a-e25817d982d9} with purposes ('C:\SfDevCluster\Data\_App\_Node_4\TestMicroServicesType_App22\PublicApiPkg.Code.1.0.1', 'OpenIdConnectServerHandler', 'AccessTokenFormat', 'ASOS')."
"Performing unprotect operation to key {4406cfa7-a588-44ba-b73a-e25817d982d9} with purposes ('C:\SfDevCluster\Data\_App\_Node_3\TestMicroServicesType_App22\AuthApiPkg.Code.1.0.1', 'OpenIdConnectServerHandler', 'AccessTokenFormat', 'ASOS')."
To fix this, #PinpointTownes suggested to setup the data protection provider like so:
var redis = ConnectionMultiplexer.Connect(ConnectionHelper.GetRedisConnectionString(Configuration));
services.AddDataProtection()
// set the application name to a common value in all apps
// to have the same purpose and share the token across apps
.SetApplicationName("MyTestMicroServices")
.PersistKeysToRedis(redis, "DataProtection-Keys")
.ProtectKeysWithCertificate(CertificateHandler.GetX509Certificate2(Configuration));
Call services.AddDataProtection().SetApplicationName("[your application name]") to ensure your two APIs use the same discriminator (used to derive the crypto keys) and it should work.
Once a WebAPI access token is generated, how does WebAPI validate that token for the next request? I wonder if I can use an [Authorize] attribute, it must compare the token sent by the client with the token at the server side, if stored somewhere. Does it just check if token is present and not its value?
Bearer token
First of all, your Identity Provider or Token Provider which issues the authorization tokens needs to have the same machine key settings as the Web Api application for encryption/decryption:
<machineKey
decryptionKey="B7EFF1C5839A624ED0268917EDE82F408D2ECBFAC817"
validation="SHA1"
validationKey="C2B8DF31AB9624D8066DFDA1A479542825F3B48865C4E47AF6A026F22D853DEC2B3248DF268599BF89EF78B9E86CA05AC73577E0D5A14C45E0267588850B"
/> </system.web>
Because under the hood Bearertoken uses MachineKey encryption.
In other words if you dont have the same settings, your web api won't be able to decrypt the token (validate it).
This is done automatically by:
Microsoft.Owin.Security.OAuth.dll
using middleware.
You can use the Authorize Attribute on your web api controllers/actions if you want simple authorization with Usernames or roles like this:
[Authorize(Roles="Administrators,Managers",Users ="Mike,Laura")]
If you want custom authorization, then you have to implement a custom authorization attribute which will handle the custom authorization in your web api. If the user is not allowed to pass you will return a 401 UnAuthorized Response:
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add("WWW-Authenticate","Bearer location='http://localhost:8323/account/login'");
For example:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class CustomAuthorizeAttribute : System.Web.Http.Filters.AuthorizationFilterAttribute
{
public RulesExampleEnum[] Rules { get; set; }
public string Id { get; set; }
.....
// Summary:
// Calls when a process requests authorization.
//
// Parameters:
// actionContext:
// The action context, which encapsulates information for using System.Web.Http.Filters.AuthorizationFilterAttribute.
public virtual void OnAuthorization(HttpActionContext actionContext);
public virtual Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken);
and register it in your webApiConfig.cs
config.Filters.Add(new CustomAuthorizeAttribute());
and apply it on Web Api controller or action:
[CustomAuthorize(Id = "AnyId", Rules = new RulesExampleEnum[] { RulesExampleEnum.Rule1, RulesExampleEnum.Rule3 })]
public IEnumerable<object> Get()
{...
Once access token is generated, client must include the access token inside Header for each request.
Client may set the access token inside Authorization HTTP Header.
On the server side, you should create class to handle the Authorization, which is a derived class from System.Web.Http.AuthorizeAttribute, something like below :
public class AuthorizationHandlerAttribute : AuthorizeAttribute
{
string AccessTokenFromRequest = "";
if (actionContext.Request.Headers.Authorization != null)
{
// get the access token
AccessTokenFromRequest = actionContext.Request.Headers.Authorization.Parameter;
}
string AccessTokenStored = "";
// write some code to get stored access token, probably from database
// then assign the value to a variable for later use
// compare access token
if (AccessTokenFromRequest != AccessTokenStored)
{
// if the token is not valid then return 401 Http Stasus
// or simply call base method
base.HandleUnauthorizedRequest(actionContext);
}
}
Then you use the newly created class and attach it on controller or action you wished to protect from unauthorized access.
public class UsersController : ApiController
{
[AuthorizationHandler]
public User Get(int id)
{
// only request with valid access token will reach this
}
}
The secret key is transmitted in the header of the request from the client to the server, and the contents are validated at the server at each request where the [Authorize] attribute is used.
You can use a tool like Fiddler from Telerik (free) to see the data being transported, but not the content (since its encrypted). Inspecting raw web traffic is invaluable when working with MVC / WebAPI, so I highly recommend it. Here's a link to Fiddler, although other similar tools exist as well.
http://www.telerik.com/fiddler
To answer the second part of your question, the server absolutely checks the contents of the secret key before allowing the request to proceed as authorized.
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 do I even begin coding authentication using ASP.NET Web API so it is cross-platform to support desktop, mobile and web? I'd read of some methods of doing RESTful authentication, such as using tokens in the header.
Are there any example projects out there that utilizes this method?
Questions:
If not how do I fix the [Authorize] attribute to read the token?
How do I generate this token? I dont think i can use formsauthentication because that uses cookies.
How do I handle the actual authorization, do the client send raw password and username then I generate the token or is there some other way?
How do I handle when my website is using it? I heard this is handled differently than when an app is using it, such as getting the domain and authorizing it.
I think tokens would be a solid way to go. Forms authentication is based on cookies for the web. Not the most idea situation for all non browser clients though.
What I'd suggest is creating a custom AuthorizationFilterAttribute and overriding the OnAuthorization method. In that method, you could check for the existence of a token that you've issued to the client after they've supplied valid credentials. You can use this attribute on any method or controller you want validated. Here's a sample you might reference
public class AuthorizeTokenAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext != null)
{
if (!AuthorizeRequest(actionContext.ControllerContext.Request))
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized) { RequestMessage = actionContext.ControllerContext.Request };
}
return;
}
}
private bool AuthorizeRequest(System.Net.Http.HttpRequestMessage request)
{
bool authorized = false;
if (request.Headers.Contains(Constants.TOKEN_HEADER))
{
var tokenValue = request.Headers.GetValues("TOKEN_HEADER");
if (tokenValue.Count() == 1) {
var value = tokenValue.FirstOrDefault();
//Token validation logic here
//set authorized variable accordingly
}
}
return authorized;
} }
TOKEN_HEADER is just a string representing an HTTP header that the client should pass back for authenticated requests.
So let's walk through it
Client requests secure data
Client is not authorized, return a response with an Unauthorized status code
Client sends credentials to authenticate, which should be secured via HTTPS
Once validated, client receives a token via an HTTP header, or whatever works for you
Client tries requesting secure data again, this time attached the token to the request
The AuthorizeTokenAttribute will validate the token and allow the action to execute.
Also, check this post by John Petersen. Making your ASP.NET Web API’s secure
There are lots of ways to authenticate users for a REST service. Using tokens is possible but just using Basic Authentication is even simpler and about as standard and cross platform as you can go.
Don't confuse authorization with authentication. The [Authorize] attribute is all about authorization but only after a user has been authenticated using some other mechanism. Authorization is completely useless without doing proper authentication first.
The best resource to check is Dominick Baier who is an expert on the subject.
I use a very simple approach:
define an access profile with its unique accessId and accessKey (e.g. MD5 hashed GUID value)
store such access profile in database
every request (GET/POST/etc.) must supply accessId, queryHash (MD5 hash value represents the query) and signature (MD5 hash value of queryHash + accessKey). Of course the client needs keep the accessKey in a secure place!!!
server gets the request will check the accessId and the signature using the same calculation algorithm to reject or grant the access (authenticate)
further authorization can be done on request type basis utilizing the access profile
the service with this approach using the new ASP.NET MVC web API can serve whatever type of client: browser/javascript and native(desktop or mobile) etc.
U can use ActionFilterAttribute and override the OnActionExecuting method.
Later on register this filter in global.cs to apply this filter for all the actions like this in Application Start method
var config = GlobalConfiguration.Configuration;
config.Filters.Add(new CustomAuthAttribute ());
{
namespace Customss
{
Public class CustomAuthAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
// To inforce HTTPS if desired , else comment out the code
if (!String.Equals(actionContext.Request.RequestUri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
{
Content = new StringContent("HTTPS Required")
};
return;
}
// get toekn from the header
var userToken = actionContext.Request.Headers.GetValues("UserToken");
// Customer Logic to check the validity of the token.
// U can have some DB logic to check , custom STS behind or some loca cache used to compare the values
}
}
}
}