ServiceStack.NET porting authentication from ASP.NET - servicestack

in an existing Silverlight application,I'm substituting WCF Services with ServiceStack's ones... I've successfully managed to port all the service and tested them..I've got one last point to look at...the authentication
Currently in I use an Asp.NET authentication based on a CustomMembershipProvider that checks with some criteria if a user can access to the application.
In each of my Services method I've something as
public bool DoSomething(int idUser, string prefix)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated) throw new SecurityExeption();
//some computation
return res;
}
And it works fine...
Now I was tring to implement the same thing on ServiceStack,I've created my AuthProvider as follow
public class myAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
if (userName == "test" && password == "test")
return true;
return false;
//return base.TryAuthenticate(authService, userName, password);
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
authService.SaveSession(session, SessionExpiry);
}
}
And tested it on a sample project (I promise I'll remove test/test before deploying it!)
I've tried to check if HttpContext.Current.User.Identity.IsAuthenticated is valid after I've authenticated via SS Service but I got a false... am I doing something wrong or ServiceStack won't build authentication on asp.net? am I hinering from the wrong AuthProvider? I wish to have all the asp.net feauter persisted as sliding period/session timeout via web.config and so on
Thanks

Possible Duplicate but may be different because you're on Silverlight.
Use ASP.NET Membership in ServiceStack
Based on Documentation:
"ServiceStack's Authentication, Caching and Session providers are completely new, clean, dependency-free testable APIs that doesn't rely on and is devoid of ASP.NET's existing membership, caching or session provider models."
https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization
If you're using a the service stack JsonServiceClient, there is nothing that will automatically fill in any authentication information in your request. Additionally, once you make your service run on ServiceStack, you're opting out of any MS built-in authentication schemes. See Mythz answer on how you can run an ASP.NET site side by side with a shared session and whether that can apply to your situation.
I have a hunch that in your custom Auth Provider, the username and password being passed in to TryAuthenticate is either NULL or empty.

Related

Identity Server 4 asp.net 2.1 - IProfileService or alternative

I will buy anyone a beer who can solve my problem!
As a piece of work I need to update our Identity Server to use an implicit login flow, it was currently using Bearer Token access only. As a part of our architecture we are using Multi-tenancy.
For security reaosns we need to check the tenant header to verify that the user is not impersonating another tenant. To do this from a client perspective we use a custom IProfileService. This gets triggered in the middleware of Identity Server, meaning all is good!
However if I was a user and I wanted to use some form of functionality on Identity Server itself and not an actual client of it, then IProfileService will not be triggered. An example of this would be to revoke access to clients, or even log out.
The GetProfileDataAsync Method on IProfileService is Invoked when the client request additional claims for the user.
germansak on Github Issue here had a similar issue and it was never quite answered (https://github.com/IdentityServer/IdentityServer4/issues/1643)
Leading to my question, how has anyone been able to verify a Tenant on Identity Server itself when they are not going through a Client, but instead Identity Server. If I can't trigger IProfileService I feel as if I'm beat!
Both logout and grants functionality is not part of the identity server 4 core package and they are simply implemented as ASP.NET Core razor views outside of the oauth2 flows.
There are few ways to validate headers therefore, I guess the easiest in my opinion would be to add another middleware.
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<TenantHeaderValidationMiddleware>();
...Your other config
}
public class TenantHeaderValidationMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
string tenantId = Request.Headers["YourTenantIdHeader"];
//do the checking
...Validation logic
//pass request further if correct
await _next(context);
}
}

How does [Authorize] attribute enhance Azure App Service (web app) authentication/authorization

I published a web app to Azures App Services. I used the App Service's Authentication/Authorization feature to provide security. I successfully added Active Directory features to my web service (and desktop client). It seemed to work very well. Couldn't access data from a browser or desktop client without signing in to the AD.
This was all before I added the [Authorize] attribute to any of the controllers in the API!
So, what will [Authorize] do (or add) to security in my web api. It seems to already be locked up by configuring the Authentication/Authorization features of the web app in Azure.
So, what will [Authorize] do (or add) to security in my web api.
Using ILSpy, you could check the source code about AuthorizeAttribute under System.Web.Mvc.dll. The core code for authorization check looks like this:
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
}
if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
{
return false;
}
if (_rolesSplit.Length > 0)
{
string[] rolesSplit = _rolesSplit;
IPrincipal principal = user;
if (!rolesSplit.Any(principal.IsInRole))
{
return false;
}
}
return true;
}
The main process would check httpContext.User.Identity.IsAuthenticated, then check whether the current user name, user role is authorized or not when you specifying the allowed Users,Roles.
For Authentication and authorization in Azure App Service(Easy Auth) which is implemented as a native IIS module. Details you could follow Architecture of Azure App Service Authentication / Authorization.
It seemed to work very well. Couldn't access data from a browser or desktop client without signing in to the AD.
This was all before I added the [Authorize] attribute to any of the controllers in the API!
Based on your description, I assumed that you set Action to take when request is not authenticated to Log in with Azure Active Directory instead of Allow Anonymous requests (no action) under your Azure Web App Authentication/Authorization blade.
Per my understanding, you could just leverage App Service Authentication / Authorization which provides built-in authentication and authorization support for you without manually adding middleware in your code for authentication. App service authentication would validate the request before your code can process it. So, for additional custom authorization check in your code, you could define your custom authorize class which inherits from AuthorizeAttribute to implement your custom processing.
public class CustomAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//TODO:
}
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
//TODO:
}
}
Then, decorate the specific action(s) or controller(s) as follows:
[CustomAuthorize]
public class UsersController : Controller
{
//TODO:
}
App Service's Authentication/Authorization feature is Based on IIS Level. [Authorize] attribute is based on our code level. Both of this can do Authentication, if you used both of them, it means that there are two levels of authentication in your web app.
Here is a picture that helps you understand them:

Authenticate server to server communication with API key

I have a couple of self-hosted windows services running with ServiceStack. These services are used by a bunch of WPF and WinForms client applications.
I have written my own CredentialsAuthProvider. My first implementation of the user database was on MSSQL server using NHibernate. Now since the system is growing I reorganize things a bit. I have created a central 'infrastructue' service which uses Redis as data store and is responsible for account management, central configuration and preferences management. Later it will also contain central logging and RedisMQ. All accounts, roles etc are now stored there (instead of MSSQL). Account migration was successfuly and authentication works fine so far.
Now I have the problem, that clients and servers need to get and set their configurations / preferences. This means that my servers are also clients since they not only serve client requests for their specific business domain but itself need to call the 'infrastructure' server to load / update its own configuration and later log entries and messages.
To authenticate such requests I thought an API key is a good way to go. These requests are not user related and therefore do not need a gateway functionality, they simply need some communication with the central infrastructure server. So I was reading the ServiceStack docs about the API Key Provider, but unfortunately for me a lot remains unclear.
Here first some relevant code from my 'infrastructure' server's Configure method:
private PooledRedisClientManager RedisBusinessPool { get; set; }
//...
container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(connStrBus));
container.Register(c => new AppUserRepository(RedisBusinessPool));
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BediCredentialsAuthProvider(),
}
));
// For the API keys I tried:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings)
{
KeyTypes = new []{"secret", "publishable"},
},
}
));
Since I enabled the API Key plugin I get an error on the client when I try to login:
ERROR; AccountManagerWinDesktop; [LoginViewModel+<Login>d__50.MoveNext]; - <username> failed to login to server <myInfrastructureServer>. Exception: 404 NotFound
Code: NotFound, Message: No configuration was added for OAuth provider 'credentials'
Does this mean, that I have to implement my own ApiKeyProvider to cooperate with my implementation of the CredentialAuthProvider? If so, what do I need to add?
In my CredentialAuthProvider implementation I have overwritten Logout, Authenticate, OnAuthenticated and TryAuthenticate. A WPF client offers a UI to store users and roles. They are stored on the Redis database including hashed passwords etc. In my TryAuthenticate implementation I simply have:
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
AppUser user = null;
try
{
//the repository handles all Redis database access
var userRepo = HostContext.TryResolve<AppUserRepository>();
user = userRepo.GetAppUser(userName);
if (user == null)
throw HttpError.NotFound("User '{0}' not found. Please try again.".Fmt(userName));
authService.Request.Items.Add("AppUser", user);
var pwdMgr = new PwdManager();
var hpwd = pwdMgr.GetHashedPassword(password, user.Salt);
if (hpwd == user.Password)
{
//do stuff
}
else
{
// do other stuff
}
return hpwd == user.Password;
}
catch (Exception ex)
{
Log.Error($"Error retrieving user {user} to authenticate. Error: {ex}");
throw;
}
}
What I do not understand right now - Questions:
How are API keys related to my own implementation of CredentialsAuthProvider?
How can I issue API keys to an application server? (I read that ServiceStack creates keys automatically when a user is created, but I do not need this in my scenario)
Do I also have to implement my own ApiKeyAuthProvidersimilar to the CredentialsAuthProvider I have overwritten? If so, is there a sample somewhere?
Is there any object / data model for API keys?
Do I need to implement something like the TryAuthenticate method above to verify my API Keys?
You should only ever register 1 of any Plugin type, so change your AuthFeature plugin to register all Auth Providers you want to enable, e.g:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BediCredentialsAuthProvider(),
new ApiKeyAuthProvider(AppSettings)
{
KeyTypes = new []{"secret", "publishable"},
},
}
));
How are API keys related to my own implementation of CredentialsAuthProvider?
An API Key is assigned to a User, i.e. when a request is received with an API Key, they're authenticated as the user the API Key is assigned to. API Keys are created for each new user that's registered, the above configuration creates a secret and publishable key for a new register created with the /register service.
API Keys requires using a User Auth Repository
Your users need to be persisted in an AuthRepository in order to use the API Key AuthProvider. The list of support Auth Repositories are listed on in the documentation. Although you can use your own custom User Auth Repository if it implements IUserAuthRepository and IManableApiKeys interfaces.
How can I issue API keys to an application server? (I read that ServiceStack creates keys automatically when a user is created, but I do not need this in my scenario)
An API Key is assigned to a User - all of ServiceStack AuthProviders revolves around Authenticating Users. One idea is to create a "User" to represent that App Server. You can use the IManageApiKeys API to create your own API Keys, there's an example of using this in the code-snippet for creating API Keys for existing Users.
Do I also have to implement my own ApiKeyAuthProvider similar to the CredentialsAuthProvider I have overwritten? If so, is there a sample somewhere?
You wont need to implement anything to use the existing ApiKeyAuthProvider but if it doesn't do what you need you can take ApiKeyAuthProvider.cs and create a customized version that does what you need.
Is there any object / data model for API keys?
The ApiKey class is the model that contains the API Key itself, which is persisted in all supported Auth Repositories.
Do I need to implement something like the TryAuthenticate method above to verify my API Keys?
No.

How to share an Access Token between an MVC 5 web application and Web API 2 application

In this instance I am having the user log into the (MVC 5) Web application, which then acts as proxy to log into the (Web API 2) API (using basic over SSL) and return a Bearer/Access Token. I'm using the Thinktecture.IdentityModel.Client.OAuth2Client to handle the login and get the access token, which all works fine.
Some other stuff happens but now I want the Web application to be able to decode the Access Token to access the claims set on the API (specifically the user ID returned after login to the API).
I'm using the much demoed, UseOAuthAuthorizationServer and UseOAuthBearerAuthentication extension methods with a token endpoint pretty much out of the box but with a custom OAuthAuthorizationServerOptions.Provider to access my own repository.
I have the same MachineKey on both applications, but I am unclear how to decode the token , although I understand I would probably have to use the SecureDataFormat.Unprotect method.
The closest attempt I have in the Web application is:
Task<TokenResponse> response = client.RequestResourceOwnerPasswordAsync(model.Email, model.Password);
IDataProtector dataProtecter = Startup.DataProtectionProvider.Create("does this matter?");
TicketDataFormat ticketDataFormat = new TicketDataFormat(dataProtecter);
AuthenticationTicket ticket = ticketDataFormat.Unprotect(response.Result.AccessToken);
With the Startup.DataProtectionProvider set as follows:
public partial class Startup
{
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
this.ConfigureAuth(app);
}
}
My fall back plan is to offer an API method that returns the information I am interested in after login, but it seems excessive seeing as it forms part of the claims in the token (as I understand it).
I have tried to wrap my head around JWT (I've looked at Thinktecture, Microsoft source code and various other forums), but not sure if that would help (although claims being available in plain text us useful). I have yet to find an example that allows sign in with basic authentication and returns a custom JWT containing an access token.
Anyway I hope thats enoguh information and any help would be much appreciated... cheers
You guys got very close. Shadi was on the right track. Even if this is a separate mvc application, you still need to decrypt the token as shown and extract the claim. If your web api token is in the variable called accessToken, you can do the following in your mvc web app. (Note that mvc is using both bearer authentication and cookie authentication and OAuthBearerOptions is a static class)
//Unprotect the token
var unencryptedToken = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(accessToken);
//Extract the claims identity from the token
var identity = unencryptedToken.Identity;
//Once you have the claims identity extracted, create a new claims identity that uses
//ApplicationCookie as the default authentication type
var id = new ClaimsIdentity(identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
// Now you are ready to sign in with your new claims identity. You basically created an
//application cookie from a bearer token and now using this cookie to sign-in
AuthenticationManager.SignIn(id);
Here is how your startup.auth.cs should include (note that we have an OAuthBearerAuthenticationOptions static member and we call app.UseOAuthBearerAuthentication() just to be able to decrypt the bearer token
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
static Startup()
{
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
}
public void ConfigureAuth(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
}
If you are using the UseOAuthBearerAuthentication you can make the OAuthBearerOptions as static on the Startup.Auth.cs class:
public partial class Startup
{
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
...
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
...
}
}
Now from anywhere in the code you can unprotect the received token this way:
var ticket = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(response.Result.AccessToken);
Now you can use the ticket for your access the claims for the API user:
ticket.Identity.Claims
Hope this would answer your question.
EDIT
This answer on SO would solve your problem please have a look.

Where should I plugin the Authorization in Asp.net WebAPI?

As I see I have 3 possible places to plug my stuff in the pipeline
1) AuthorizationFilters
2) Action Filters
3) DelegatingHandler
The most obvious one is AuthorizationFilters , where I can decorate my actions/ controllers with my custom authorization attribute . say .. MyCustomAuthorizationAttribute .
Since HTTP message handlers are in the first stage in the processing pipeline. Does it make any sense to put it in there ?
Authorization for me right now simply means checking a token in the header which is given to the client after authentication.
Update July 2014
My original answer covered WebApi 1. with WebApi 2 there were some changes i.e. there is now an IAuthenticationFilter meaning you can move authentication logic out of the DelegatingHandler which is a little more elegant.
There is a Nuget project here that offers an implementation of IAuthenticationFilter and also explains some background to its introduction.
OWIN middleware is now perhaps the best place to implement your authentication logic - there is an example of Certificate Authentication here and Basic Authentication OWIN Middleware here in this blog post the former example is the preferred one as it demonstrates the use of the base AuthenticationHandler class.
The advice on AuthorizationFilters remains largely unchanged.
End Update
Typically...
Use DelegatingHandler to carry out Authentication... i.e. who someone is. Use this to set the Principle of the Thread and User context, add claims etc. You can place authorisation logic here too but on a fairly global scale. I would personally always use AuthorizationFilters for authorisation.
Use AuthorizationFilters to restrict controllers and actions to specific people. These are used when you can extrapolate their permission with the information in claims, principal, url or the http request parameters. The default authorisation filter can be used to restrict access to anonymous users or by roles (if set in something like a delegating handler) - obviously you can implement your own AuthorizationFilters too if you need it.
Occasionally use ActionFilters when you need to make the decision over authorisation using the message content e.g. you need access to a property on the entity to decide whether they have access (obviously be careful with this(!)).
Note:
The AuthorizationFilters are called before the content of the body is read therefore they do not have access to the message body to make authorization decisions this is why the ActionFilters specifically the OnActionExecuting is used to occasional raise authentication errors.
So
In your scenario I would put a simple DelegatingHandler to take your header and set the principal.
public class CustomAuthenticationMessageHandler : DelegatingHandler
{
public CustomAuthenticationMessageHandler ()
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
Authenticate(request);
return base.SendAsync(request, cancellationToken);
}
protected virtual void Authenticate(HttpRequestMessage request)
{
var authorisationHeader = request.Headers.Authorization;
if (authorisationHeader == null)
{
return;
}
//Ensure you are happy with the header contents then
{
var principal = new GenericPrincipal(//new Identity , //Roles);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
}
}
}
Then use AuthorizationFilters to restrict access:
[Authorize]
public string Get()
{
}
[Authorize(Roles = "Admin")]
public string GetAdminOnly()
{
}
To register the global Authentication
config.MessageHandlers.Add(new CustomAuthenticationMessageHandler());
This will mean that in every request the principal will be set to either null or a valid identity. It won't handle authorisation i.e. wont deny access to any controllers or actions.
To start protecting resources
Either target protected controllers and actions with the standard or custom [Authorize] attributes. Or register globally:
config.Filters.Add(new AuthorizeAttribute());
And only white list the controllers and actions you want unsecured using the [AllowAnonymous] attribute.
If you only want authentication on some routes
Then you can modify your DelegatingHandler a little to set the InnerHandler to route to the correct controller e.g.
public CustomAuthenticationMessageHandler(HttpConfiguration configuration)
{
InnerHandler = new HttpRoutingDispatcher(configuration);
}
And then you can specify this handler on your routes like so:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "myurl",
defaults: new {},
constraints: new {},
handler: new CustomAuthenticationHandler(config)
);

Resources