I started working on Web Api and just want to create a simple basic authentication. I want to know how to do that?
I tried with the given MSDN link but no step wise tutorial is given on MSDN.
http://www.asp.net/web-api/overview/security/basic-authentication
The link you gave provides much of the detail you need, I hope this fills in the blanks.
Note: If using Web.API 2, Microsoft are suggesting a different approach using authentication filters.
Set up https on your server
This is quite important if you need real security otherwise passwords can be gleaned by snooping parties. How you do this depends a entirely on your setup, which you don't detail, but if you're working on an Azure WebRole there's a pretty good step-by-step guide to setting up SSL from Microsoft.
This isn’t required for the next steps, but should be done before you release your code. I mention it first because this part usually involves getting other people involved (sysadmin for server config, finance to purchase the certificate, etc) and it’s good to give them lots of warning.
Write (or steal) a custom IHttpModule to do your authentication
This is the big block of C# code in your link - it parses the values sent by the browser and sets HttpContext.Current.User to the authenticated user. Just copy and paste the meat into a class in your own application and we’ll come back to it later. You’ll need the following using statements in your code.
using System; using System.Net.Http.Headers; using System.Security.Principal;
using System.Text; using System.Threading; using System.Web;
Associate that module with your application
Add a new module to your web.config file (note system.webServer probably already exists)
<system.webServer>
<modules>
<add name="BasicAuth" type="Full.ClassName.Path.BasicAuth, Assembly.Name"/>
</modules>
</system.webServer>
Restrict access to the relevant parts of your site
You can block specific actions by adding the [Authorize] attribute before the action definition. Block a whole controller by adding it before your controller class.
[Authorize] // Restricts access to whole controller
public class StockController : ApiController {
[Authorize] // Restricts access to this action - not necessary if whole controller restricted.
public IEnumerable<StockLevel> Get() {
Or in your App_Start\WebApiConfig.cs file you can add config.Filters.Add(new AuthorizeAttribute()); and it will lock everything down.
Something to watch out for - there’s also a System.Web.Mvc.AuthorizeAttribute so if you have that namespace included you can get confusing results.
At this point you can try it out - user: "user", pass: "password".
Customize your user validation
Go back to the class we stole from the link and you'll see the following block of code:
// TODO: Here is where you would validate the username and password.
private static bool CheckPassword(string username, string password)
Alter this to return true if the username and password are valid. If you're rolling your own you may want to investigate bcrypt (do you trust the implementation you downloaded off the net?), PBKDF2 or the Crypto class (simple but not terribly secure) but there's probably something better from Microsoft as there are lot of concerns around storing passwords properly.
I had to add a few lines of code to the MSDN example to get it to work. Specifically, in OnApplicationAuthenticateRequest(), I set the response status code to 401 if the user could not be validated:
private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
{
var request = HttpContext.Current.Request;
var authHeader = request.Headers["Authorization"];
bool validated = false;
if (authHeader != null)
{
var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
// RFC 2617 sec 1.2, "scheme" name is case-insensitive
if (authHeaderVal.Scheme.Equals("basic",
StringComparison.OrdinalIgnoreCase) &&
authHeaderVal.Parameter != null)
{
validated = AuthenticateUser(authHeaderVal.Parameter);
}
}
if (!validated)
{
HttpContext.Current.Response.StatusCode = 401;
}
}
Once I did that, it worked fine. There's probably better ways to structure the logic, but this is about the smallest change from the example that does the job.
To selectively enable basic authentication on a per-controller or per-method basis, you can derive from AuthorizeAttribute as described in this question.
Related
I have an ASP.NET Core 2.2 application where I am displaying some documents. Most documents are public, so anonymous access is fine. However, some documents are private (i.e. they require authentication/authorization), and in the future some documents might also require a valid subscription. All documents are retrieved using the same actions, so we only know the required permissions after the documents have been loaded. We also load some resources as static files (IApplicationBuilder.UseStaticFiles), but I guess that shouldn't really be an issue as StaticFileOptions.OnPrepareResponse can be used for custom authorization code.
The logic for who gets access to private documents is currently really simple. And at the moment, we only display documents, we don't allow any other kind of operation on them (editing, deletion etc.). To me, this sounds like a pretty standard case of resource-based authorization.
Anyway, I have found this article and from what I've understood, I need to define a policy (identified by a magic string - what's up with that?!) as well as a requirement and an AuthorizationHandler<MyRequirement, MyResource> which will perform the actual authorization logic. Then, inside my controller action, I will need to call IAuthorizationService.AuthorizeAsync and pass in the user, the resource and the policy name (the magic string) and, based on the result from that method, allow or deny access. That seems more than convoluted for what I'm trying to accomplish. It would probably be easier if I simply defined my own kind of "authorization service" and simply dropped the whole policy and requirement stuff. I also think it's less than ideal that I would have to replicate the if-else logic in all affected controller actions.
Surely I'm not the only one with this issue. Is there something I've missed?
If there are indeed good reasons for using policies and requirements, how would you name them in a case like this? I'm really feeling a little lost.
Maybe it would make sense to use the type of document (public, private, subscribers-only) as the policy name?
In the end, we didn't want to deal with this stuff and just wrote our own AuthorizationService, which is injected into the controller like any other service.
It loads the required permissions for all documents the first time it is used and caches them.
Our controller methods then look something like this:
[HttpGet("[action]")]
public async Task<Document> GetDocument(string documentId)
{
if (_authorizationService.MayAccess(User, documentId))
{
return _documentRepository.GetDocument(documentId);
}
else
{
Response.StatusCode = StatusCodes.Status403Forbidden;
return null;
}
}
I recommend the last approach explained in this article - https://www.red-gate.com/simple-talk/dotnet/c-programming/policy-based-authorization-in-asp-net-core-a-deep-dive/
Allows you to keep you controller clean, by just applying annotation with the name of the policy. In the handler you must implement the logic checking if person can access the resource - it can be based for example on checking a property ownerId in a resource(for example in database table column) or a member of a certain group in AD, or anything else.
EDIT:
Using Requirements and RequirementsHandlers - I have done something similiar.
I don't know how should your logic exactly work, so I am just going to assume some.
lets say you have a get endpoint: documents/documentId
You want to apply logic which will make this document accessible only to the document owner. Obviously, you need somewhere to store who is the owner of the document, so lets keep that in property of a document entity.
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IsDocumentOwner requirement, DocumentRepository documentRepository)
{
if (context.Resource is AuthorizationFilterContext ctx)
{
var documentId = ctx.RouteData.Values["documentId"]?.ToString();
//here load document from repo and check if the property ownerId is equal to current user id
var userId = context.User.Claims.FirstOrDefault(x => x.ToString().Contains(oid))?.Value;
//if yes, make the request pass to the body of a controller with the attribute
context.Succeed(requirement);
}
}
implement IsDocumentOwner:
public class IsDocumentOwner : IAuthorizationRequirement
{
}
in your Startup.cs add:
services.AddAuthorization(options =>
{
options.AddPolicy(
nameof(IsDocumentOwner),
policyBuilder => policyBuilder.AddRequirements(
new IsDocumentOwner()));
});
then, last step, apply attribute on your controller method
[Authorize(Policy = "IsDocumentOwner")]
[HttpGet("{documentId}")]
public YourDocumentObjectResultClass GetDocument([FromRoute]string documentId)
{
//stuff you do when current user is owner of the document, probably just display the doc
}
To your IsDocumentOwner handler you can inject any service by constructor(visualised by repository above), for example, to check if the user is a member of a group on azure ad
I'm moving a Web Api 2 project to MVC 6, since Microsoft is merging the two APIs in ASP.NET 5. In my WebApi project I had a custom Attribute Filter class that would authenticate, authorize and prevent transaction replays using a combination of public key, private key and HMAC authentication (basically, doing this with some tweaks to fit into my project).
Now in MVC6, as far as I understand I must stop using anything in the Microsoft.Web.Http namespace and instead use Microsoft.AspNet.Mvc. So I have done that, but the Microsoft.AspNet.Mvc.Filters doesn't seem to have any equivalent of Web Api 2's IAuthenticationFilter.
This is a problem for me because my customer AuthenticationFilter implemented all of IAuthenticationFilter, with all the logic in there. More importantly, it was using the Context to temporarily store the public key of the account, so my controller could access it to load up the account in turn.
So my question is, what is the proper way to filter requests in MVC6, using an Authentication Filter-like class to intercept the requests and return the appropriate status codes? I can't find any article that goes specifically in these details (they all tend to cover MVC5).
I know it's an older question, but hopefully someone (maybe even yourself) might find value in the answer.
MVC6 does in fact have an alternative. You have an
public abstract class AuthorizationFilterAttribute :
Attribute, IAsyncAuthorizationFilter, IAuthorizationFilter, IOrderedFilter
which basically tells you, that you can create your custom class, derive it from this (namespace of all of these interfaces, btw, is Microsoft.AspNet.Mvc.Filters and that should be it. You can either decorate the action with it, or you can do this in Startup.cs, to apply to all actions:
public void ConfigureServices(IServiceCollection services)
{
// Add MVC services to the services container.
services.AddMvc(options =>
{
// add an instance of the filter, like we used to do it
options.Filters.Add(new MySpecialFilter());
});
services.AddTransient<LogFilter>();
}
If you want to use a bit more logic in the filter (e.g. my LogFilter above) which is instantiated through DI, you need to use either Service Filters or Type Filters.
You can now decorate the actions with [ServiceFilter(typeof(LogFilter))] or use o.Filters.Add(new ServiceFilterAttribute(typeof(LogFilter))); in the Startup.cs file. But keep in mind, to do this you need to register the type with the DI container, like I did above with the .AddTransient<>() call.
IAuthenticationFilter is no more and IAuthorizationFilter simply does not replace it in MVC 6
Reason: authentication is NOT EQUAL to authorization.
Therefore IMO the authentication filter should stay available!
I need to access the user's password in a Jetty application after authentication, and can't figure out how.
I am migrating a set of web pages away from basic authentication in an embedded Jetty servlet application. I cannot, however, completely remove basic authentication from all of the services that these pages call, so I need to forward the user credentials in some cases, which means storing and later retrieving the user's password.
I introduced forms authentication to the root context via the standard markup in web.xml, which works fine but I can find no way of getting the user credentials programatically. As far as I can tell there is no way to place a Filter on j_security_check to intercept and store the form parameters in the session state. Jetty provides all the user credentials in the session state but this is in a container-specific key and although the application is currently tied to Jetty I would strongly prefer a container-agnostic solution. Here are some specific questions that I've tried to formulate after going down a number of seemingly dead-end streets:
How can I obtain the user's password after login? Even if I moved the services away from basic authentication I would still need to perform some secondary action such as obtaining a token, in which case I would still need their credentials under my control for a brief period.
Assuming I can't obtain the user's password directly, perhaps I can leverage something in the container to store the credentials. I can implement my own LoginService that wraps the actual implementation, but that class does not have access to the HttpSession or Request objects. Where is the proper place to do this?
If I need to implement a custom login solution, I'm not quite sure where to start...the FormAuthenticator has a lot of complicated session state management that I would like to preserve and not reproduce willy-nilly, and I would still prefer to defer to the container standard as much as possible. Is there some standard method for extending or overriding the j_security_check logic?
I finally found one solution, for anyone else attempting similar - and I've found quite a few other posts from confused devs, and some badly hacked together workarounds. I believe this one is correct, although you must do the URL filtering yourself and it leaves open the question as to why this is possible, if indeed j_security_check should be exempt from this type of interception for security reasons, as is claimed many places online. Perhaps I am merely exploiting an unknown gap in the Jetty security measures, so I will leave this question open for a while to see if there is a more robust or explicit solution.
ServletRequestListener allows you to latch onto the j_security_check post request before it is fully initialized. There you can get both the form parameters and the session object. So in the end it was just a matter of exhausting every possible servlet-related class in Jetty until I found one that would give me access to the j_security_check request. Some code:
public class PreAuthenticationRequestListener implements ServletRequestListener {
public static final String USERNAME_KEY = "USERNAME";
public static final String PASSWORD_KEY = "PASSWORD";
#Override
public void requestDestroyed(ServletRequestEvent sre) {
}
#Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
if (request.getRequestURI().contains("j_security_check")) {
final String username = request.getParameter("j_username");
final String password = request.getParameter("j_password");
HttpSession session = request.getSession();
session.setAttribute(USERNAME_KEY, username);
session.setAttribute(PASSWORD_KEY, password);
}
}
}
There are an option in ServiceStack to add routes dynamically, using IAppHost.Routes.Add. This is quite handy as it allows reusable services to be packed in a form of plugin and attached to actual applications.
To illustrate, here's an excerpt of application host configuration that enables a plugin and attaches routes:
class AppHost: AppHostHttpListenerBase {
public override void Configure(Container container) {
// other stuff
Plugins.Add(new MyReusablePlugin());
Routes.Add(typeof(string), "/stuff", "GET");
Routes.Add(typeof(string), "/other-stuff", "POST");
}
}
The problem is, I can't find a way to specify that authentication is required for those dynamically added routes. As of ServiceStack 4.0.15 there are no overload to Routes.Add that allow specifying that those routes require authentication. Is it possible (maybe in newer versions)?
Ideally, such a mechanism should support specifying roles/permissions, just like RequiredRoleAttribue or RequiresAnyRoleAttribute.
One more thing: I'm aware of Global request filters and it looks like they are a bit too global to be a valid solution here, but I might be wrong. If it's possible to achieve the same result (including ability to specify required roles/permissions) using request filters I would be glad to accept an example of such apporach as an answer.
You can do this using the AddAttributes extension method provided on Type:
typeof(YourType).AddAttributes(new RequiredRoleAttribute("Admin"));
So you would need to do this in addition to the Routes.Add method.
I'm trying to integrate Spring Security in my web application. It seems pretty easy to do as long as you integrate the whole process of authentication and authorization.
However, both authentication and authorization seem so coupled that it's being very time-consuming for me to understand how I could split these processes, and get authentication independently of authorization.
The authentication process is external to our system (based on single sign-on) and this cannot be modified. Nevertheless, once the user succeeds this process, it's loaded in the session, including roles.
What we are trying to achieve is to make use of this information for the authorization process of Spring Security, that's to say, to force it to get the roles from the user session instead of picking it up through the authentication-provider.
Is there any way to achieve this?
If your authentication is already done using an SSO service, then you should use one of spring security's pre-authentication filters. Then you can specify a UserDetails service (possibly custom) that will use the pre-authenticated user principle to populate the GrantedAuthority's
SpringSecurity includes several pre-authentication filters including J2eePreAuthenticatedProcessingFilter and RequestHeaderPreAuthenticatedProcessingFilter. If you can't find one that works for you, its also possible, and not that hard to write your own, provided you know where in the request your SSO implementation stuffs the data. (That depends on the implementation of course.)
Just implement the Filter interface and do something like this in the doFilter method:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// principal is set in here as a header or parameter. you need to find out
// what it's named to extract it
HttpServletRequest req = (HttpServletRequest) request;
if (SecurityContextHolder.getContext().getAuthentication() == null) {
// in here, get your principal, and populate the auth object with
// the right authorities
Authentication auth = doAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
Yes, it's possible. Spring Security (like most of the rest of Spring) is interface-driven so that you can plug in your own implementations selectively for different parts of the framework.
Update: Spring's authorisation and authentication mechanisms work together - the authentication mechanism will authenticate the user and insert various GrantedAuthority instances in the security context. These will then be checked by the authorisation machinery to allow/disallow certain operations.
Use nont's answer for the details on how to use pre-existing authentication. The details of how you get the details from your session (e.g. roles ) will of course depend on your specific setup. But if you put in the GrantedAuthority instances derived from the roles pre-populated in your session by your SSO system, you will be able to use them in your authorisation logic.
From the reference documentation (slightly edited, with my emphasis):
You can (and many users do) write
their own filters or MVC controllers
to provide interoperability with
authentication systems that are not
based on Spring Security. For example,
you might be using Container Managed
Authentication which makes the current
user available from a ThreadLocal or
JNDI location. Or you might work for a
company that has a legacy proprietary
authentication system, which is a
corporate "standard" over which you
have little control. In such
situations it's quite easy to get
Spring Security to work, and still
provide authorization capabilities.
All you need to do is write a filter
(or equivalent) that reads the
third-party user information from a
location, build an Spring
Security-specific Authentication
object, and put it onto the
SecurityContextHolder. It's quite easy
to do this, and it is a
fully-supported integration approach.
The server that handles the authentication should redirect the user to the application passing to it some kind of key (a token in CAS SSO). Then the application use the key to ask to the authentication server the username and roles associated. With this info create a security context that is passed to the authorization manager. This is a very simplified version of a SSO login workflow.
Take a look to CAS SSO and CAS 2 Architecture.
Tell me if you need more information.
we have had the same requirement where we had to use spring security for authorization purpose only. We were using Siteminder for authentication. You can find more details on how to use authorization part of spring security not authentication here at http://codersatwork.wordpress.com/2010/02/13/use-spring-security-for-authorization-only-not-for-authentication/
I have also added source code and test cases at http://code.google.com/p/spring-security-with-authorization-only/source/browse/
I am trying to understand CAS authentication with our own Authorization and was getting confused since the User object in Spring Security always expects the password to be filled in and we don't care about that in our scenario. After reading Surabh's post, it seems that the trick is to return a custom User object without the password filled in. I will try that out and see if it works in my case. Hopefully no other code in the chain will be expecting the Password in the User object.
I use the authorization by this:
Inject the authorization related bean into my own bean:
#Autowired
private AccessDecisionManager accessDecisionManager;
#Autowired
FilterSecurityInterceptor filterSecurityInterceptor;
Use this bean by this:
FilterInvocation fi = new FilterInvocation(rundata.getRequest(), rundata.getResponse(), new FilterChain() {
public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException {
// TODO Auto-generated method stub
}
});
FilterInvocationDefinitionSource objectDefinitionSource = filterSecurityInterceptor.getObjectDefinitionSource();
ConfigAttributeDefinition attr = objectDefinitionSource.getAttributes(fi);
Authentication authenticated = new Authentication() {
...........
public GrantedAuthority[] getAuthorities() {
GrantedAuthority[] result = new GrantedAuthority[1];
result[0] = new GrantedAuthorityImpl("ROLE_USER");
return result;
}
};
accessDecisionManager.decide(authenticated, fi, attr);
I too did spent lot of hours investigating on how to implement custom authorization without authentication.
The authentication process is external to our system (based on single sign-on).
I have done it, as mentioned below and it Works!!! (I am sure there are many other ways to it better, but this way just suits my scenario well enough)
Scenario : User is already authenticated by external system and all information needed for authorization is present in the request
1.
Security config need to be created, enabling global method security as below.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class SpringWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
}
}
2.) Implement Spring PermissionEvaluator to authorize whether the request should be allowed or rejected
#Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
public boolean authorize(final String groups, final String role) {
boolean allowed = false;
System.out.println("Authorizing: " + groups + "...");
if (groups.contains(role)) {
allowed = true;
System.out.println(" authorized!");
}
return allowed;
};
#Override
public boolean hasPermission(final Authentication authentication, final Object groups, final Object role) {
return authorize((String) groups, (String) role);
};
#Override
public boolean hasPermission(final Authentication authentication, final Serializable targetId, final String targetType, final Object permission) {
return authorize((String) targetId, (String) permission);
};
}
3.) Add MethodSecurityConfig
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
return expressionHandler;
}
}
4.) Add #PreAuthorize in your controller as shown below. In this example, all the groups of the user are present in request header with key 'availableUserGroups'.
This is then passed on to the CustomPermissionEvaluator to verify authorization. Please note that spring automatically passes Authentication object to the method 'hasPermission'.
So in case if you want to load user and check using spring 'hasRole' method, then this can be used.
#PreAuthorize("hasPermission(#userGroups, 'ADMIN')")
#RequestMapping(value = "/getSomething")
public String getSomething(#RequestHeader(name = "availableUserGroups") final String userGroups) {
return "resource allowed to access";
}
Handling Other Scenarios :
1.) In scenario where you want to load the user before you can perform the authorization. You can use spring pre-authentication filters, and do it in a similar way.
Example link : http://www.learningthegoodstuff.com/2014/12/spring-security-pre-authentication-and.html