Owin providers in a multi tenant web application where each domain has its own providers - cookies

I'm trying to have a solution where one web application is serving multiple domains, for each domain I would like to configure its own providers, using the app id and secret for the external provider, I would like the cookie domain and the providers information to be read from a database based on the current domain name, so for example:
switch (currentDomainName)
{
case "web1.com": load cookie domain and providers information for web1.com ...
case "web2.com": load cookie domain and providers information for web2.com ...
...
}
I'm facing two major problems:
I have no HttpContext available at the Owin Startup ConfigureAuth() and I'm not sure how to determine which domain name is used early on Startup...
I understand that Startup only run once per web application, so for example, after web1.com is accessed for the first time, ConfigureAuth() will not run again for web2.com once it is already set by web1.com
I wonder if I can override some Owin methods and make it non static... or maybe find a way to implement this in a different way (but I still like to use Owin)
Where do I start?

You can get the request url and then do a lookup in the database to see what is the domain related customer. There could be a table that lists the identity providers for this domain
Example
TenantDomains
*************
TenantId URL ......
tenant1 https://tenant1.company.com
tenant2 https://tenant2.company.com
IdProviders
***********
TenantId ProviderIds ......
tenant1 Custom, Social
tenant2 Social
Here the names are used instead of identifiers for ease of readability. However, the approach still remains the same.
You could do all the above lookup in a middleware and then use the value in the Environment and then set up the pipeline based on the data or decisions made earlier.
Example:
You can access the incoming request from the OWIN Context and do all the operation that would do otherwise on a HttpRequest from the owin context's request itself.
app.MapWhen(req => req.Request.Headers.ContainsKey("Authorization"), apiAuth =>
{
// do anything that matches this request
apiAuth.UseBearerAuthentication(new BearerAuthenticationOptions());
});
HTH

Related

REST api and caching

I have a resource called Sites.
I am planning to have an endpoint as follows:
/tenant/:tenantId/sites/:siteId
The endpoint is to return a site’s tree which will vary based on the userId extracted from the JWT token.
Since it will vary based on the user requesting it, should the endpoint have userId in the URI- may be as a query parameter?
How should caching work in this case?
The sites tree returned by this endpoint will also change based on updates in another resource (i.e users/groups)
Should the cache be discarded for all users whenever there is a change in the sites resource itself or when there is a change in groups?
I am using API gateway so will need to purge cache through client cache control header when any of the resources are updated.
Since, the data will vary on the user requesting it, the endpoint should have the userId in the URI - it could be simply a path parameter similar to the tenantId and siteId
caching can be done on the basis of If-modified-since header to indicate if the data has changed or not.
The If-Modified-Since HTTP header indicates the time for which a browser first downloaded a resource from the server. This helps determine whether or not the resource has changed since the last time it was accessed.
From a security point of view if a user only can access his own sites the user id should not be on the path (or query param), because if you do that, any user can modify the URL in its browser and try to access the other user sites. To avoid that the URL should not have any userId (you can replace it with something like /me) and the service that will handle the request should extract the id information from the token
I don't know if you are using an in-memory cache of distributed cache and if sites/users/groups are different services (deployed on different servers) or if they live in the same application, anyway, when any of the resources that cache depends on are modified, you should invalidate the cache for that users

How to make Django tries multiple realms in Keycloak using openid connect?

Synopsis
We have a web app that allows internal users and external users to login, we would like to split the 2 groups of users in Keycloak with different realms, for instance, internal realm and external realm. Our ideal authentication method is OpenID Connect.
Problem
Most Django OIDC libraries allows to specify one OIDC client configuration in Django settings. However given how OIDC works one client configuration only works with one realm, because a client is configured inside a realm.
I have come across this library django-keycloak which seems to be able to configure client configurations in a database and I need to implement my own middleware to dynamically route the request to a corresponding realm, see multi-tenancy section.
Unfortunately this library has not been updated for 2 years and seems not maintained anymore.
Question
Is there an up-to-date library that has similar functionality in django-keycloak? (I will raise an issue in the repo to enquire the project status)
Apart from the multi-client configuration approach, is there a better alternative?
I do not know about django, but from the Keycloak side what you can do is to configure the external realm as an identity provider for the internal realm. You can read about identity brokering here.
For that go to the Admin Console and:
select your Internal Realm, and click on Identity Providers
On the right side of the page select Keycloak OpenID Connect from the Add provider ... dropdown menu. It will popup the Add Identity Provider form, from there set:
the alias
the Authorization URL, Token URL, Logout URL, User Info URL and Issuer to the correspondent endpoints that can be found on the external realm .well-known endpoint (i.e., <KEYCLOAK_IP>/auth/realms/<External Realm Name>/.well-known/openid-configuration)
For the Client Authentication you can select Client secret send as post
For the Client ID and Client Secret first create a new client in your external realm and use its Client ID and Client Secret here. This client:
can have Access Type confidential
Standard Flow Enabled : ON
Valid Redirect URIs set it to your Keycloak IP followed by "*", for instance <KEYCLOAK_IP>*
Web Origins : +
Save
Bear in mind that some of those configurations might have to be adapted to your own needs.
Now if everything was set correctly, at the keycloak internal realm login page will show up a new button that the users stored on the external realm can click on to authenticate against the external realm.
Now you configure your app to lend at the Internal Realm Login page, the users from your internal realm authenticate immediately there, the users from the external realm click on the new button to explicitly authenticate against the external realm.
This setup is more or less like the use case that a user wants to login into your app but using his/her social media account.

jax-rs rest webservice authentication and authorization

I have a web application that needs to allow users using different webclients (browser, native mobile app, etc) to register. After signing in they can access restricted content or their own content (like entries they create, etc).
What I did so far: I created a jax-rs rest webservice (I'm hosting my application on glassfish) that exposes the following methods:
register - user POST's his desired username/password/email/etc; if username/email is unique, an entry for this user is created in the database (I'm using Hibernate for persistence)
login - user POST's username and password. If they are ok a UUID is created and returned to the user (this will be used as a token for future requests). I have a table called logedusers, with userID, token, validSince as columns.
Here is where it gets confusing for me.
Let's say that I have another method, getUserEntries, that should return all the entries made by the user. To make this clearer, there will be a Entry table with the following fields: entryId, userId, text.
What is the best approach here?
What i do now, is I make a get request and pass in the token like this:
localhost:8080/myApp/getUserEntries?token=erf34c34
Afterwards, if the token is valid, I get the userID from the logedusers table and based on that userId, get all the entries and return them as json.
Something like this:
#GET
#Path("getUserEntries")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserEntries(#QueryParam("token") String token) {
String userId=getUserIdFromToken(token);
if (userId == null){
return Response.status(Response.Status.UNAUTHORIZED).build();
} else {
//get some data associated with that userId, put it in the response object and send it back
return Response.ok().entity(response).build();
}
}
However, what happens if I have more methods that provide data if they are called by a valid user?
I'd have to do this check at the beginning of every method.
I want to make this authorization process transparent
So, two major questions here:
Is this design ok? The whole authenticate with user/pass, server creates and stores and sends token to the user, user sends token on future requests.
What do I do if i have many endpoints that need to determine the identity of the calling user? Can I mark them with some annotations, use some sort of security provider / authenticator (where I can add my own logic for validating - eg check to see if the token isn't older than 5 days, etc).
Thanks
Is this design ok? The whole authenticate with user/pass, server creates and stores and sends token to the user, user sends token on future requests.
It's somewhat OK. The conceptual level isn't too bad (provided you're OK with self-registration at all) but the interface needs a lot of tweaking. While yes, POST to register and login is correct, for the rest of your webapp you should be pulling the identity information out of the context if you need it, and using role-based access control at the method level where you can.
Note that your container has a whole set of authentication and authorization-support mechanisms built in. Use them.
What do I do if i have many endpoints that need to determine the identity of the calling user? Can I mark them with some annotations, use some sort of security provider / authenticator (where I can add my own logic for validating - eg check to see if the token isn't older than 5 days, etc).
Do they need the identity? Or do they just need to know that the user is allowed to access them? If the latter, the easiest method is to put a suitable #RolesAllowed annotation on the method, at which point (with suitable configuration; see the JEE5 security docs). If the former, you need to get the HttpServletRequest object for the current action and call its getUserPrincipal() method to get the user's identity (or null if they've not logged in yet). This SO question describes how to go about getting the request object; there are a few possible ways to do it but I recommend injection via a #Resource annotation.
What I wouldn't do is allow users to normally provide their own identity via a #QueryParam; that's just wildly open to abuse. You can allow them to ask about other users that way, but then you need to decide whether you are going to tell them anything or not based on whether the current user is permitted to know anything about the other user. That's the sort of complex security problem that comes up in a real app, and is a good point for needing the current verified user identity.

How do I implement login in a RESTful web service?

I am building a web application with a services layer. The services layer is going to be built using a RESTful design. The thinking is that some time in the future we may build other applications (iPhone, Android, etc.) that use the same services layer as the web application. My question is this - how do I implement login? I think I am having trouble moving from a more traditional verb based design to a resource based design. If I was building this with SOAP I would probably have a method called Login. In REST I should have a resource. I am having difficulty understanding how I should construct my URI for a login. Should it be something like this:
http://myservice/{username}?p={password}
EDIT: The front end web application uses the traditional ASP.NET framework for authentication. However at some point in the authentication process I need to validate the supplied credentials. In a traditional web application I would do a database lookup. But in this scenario I am calling a service instead of doing a database lookup. So I need something in the service that will validate the supplied credentials. And in addition to validating the supplied credentials I probably also need some sort of information about the user after they have successfully authenticated - things like their full name, their ID, etc. I hope this makes the question clearer.
Or am I not thinking about this the right way? I feel like I am having difficulty describing my question correctly.
Corey
As S.Lott pointed out already, we have a two folded things here: Login and authentication
Authentication is out-of-scope here, as this is widely discussed and there is common agreement. However, what do we actually need for a client successfully authenticate itself against a RESTful web service? Right, some kind of token, let's call it access-token.
Client) So, all I need is an access-token, but how to get such RESTfully?
Server) Why not simply creating it?
Client) How comes?
Server) For me an access-token is nothing else than a resource. Thus, I'll create one for you in exchange for your username and password.
Thus, the server could offer the resource URL "/accesstokens", for POSTing the username and password to, returning the link to the newly created resource "/accesstokens/{accesstoken}".
Alternatively, you return a document containing the access-token and a href with the resource's link:
<access-token
id="{access token id goes here; e.g. GUID}"
href="/accesstokens/{id}"
/>
Most probably, you don't actually create the access-token as a subresource and thus, won't include its href in the response.
However, if you do so, the client could generate the link on its behalf or not? No!
Remember, truly RESTful web services link resources together in a way that the client can navigate itself without the need for generating any resource links.
The final question you probably have is if you should POST the username and password as a HTML form or as a document, e.g. XML or JSON - it depends... :-)
You don't "login". You "authenticate". World of difference.
You have lots of authentication alternatives.
HTTP Basic, Digest, NTLM and AWS S3 Authentication
HTTP Basic and Digest authentication. This uses the HTTP_AUTHORIZATION header. This is very nice, very simple. But can lead to a lot of traffic.
Username/Signature authentication. Sometimes called "ID and KEY" authentication. This can use a query string.
?username=this&signature=some-big-hex-digest
This is what places like Amazon use. The username is the "id". The "key" is a digest, similar to the one used for HTTP Digest authentication. Both sides have to agree on the digest to proceed.
Some kind of cookie-based authentication. OpenAM, for example, can be configured as an agent to authenticate and provide a cookie that your RESTful web server can then use. The client would authenticate first, and then provide the cookie with each RESTful request.
Great question, well posed. I really like Patrick's answer. I use something like
-/users/{username}/loginsession
With POST and GET being handled. So I post a new login session with credentials and I can then view the current session as a resource via the GET.
The resource is a login session, and that may have an access token or auth code, expiry, etc.
Oddly enough, my MVC caller must itself present a key/bearer token via a header to prove that it has the right to try and create new login sessions since the MVC site is a client of the API.
Edit
I think some other answers and comments here are solving the issue with an out-of-band shared secret and just authenticating with a header. That's fine in many situations or for service-to-service calls.
The other solution is to flow a token, OAuth or JWT or otherwise, which means the "login" has already taken place by another process, probably a normal login UI in a browser which is based around a form POST.
My answer is for the service that sits behind that UI, assuming you want login and auth and user management placed in a REST service and not in the site MVC code. It IS the user login service.
It also allows other services to "login" and get an expiring token, instead of using a pre-shared key, as well as test scripts in a CLI or Postman.
Since quite a bit has changed since 2011...
If you're open to using a 3rd party tool, and slightly deviating from REST slightly for the web UI, consider http://shiro.apache.org.
Shiro basically gives you a servlet filter purposed for authentication as well as authorization. You can utilize all of the login methods listed by #S.Lott, including a simple form based authentication.
Filter the rest URLs that require authentication, and Shiro will do the rest.
I'm currently using this in my own project and it has worked pretty well for me thus far.
Here's something else people may be interested in.
https://github.com/PE-INTERNATIONAL/shiro-jersey#readme
The first thing to understand about REST is that its a Token based resource access.Unlike traditional ways, access is granted based on token validation. In simple words if you have right token, you can access resources.Now there is lot of whole other stuff for token creation and manipulation.
For your first question, you can design a Restfull API. Credentials(Username and password) will be passed to your service layer.Service layer then validates these credentials and grant a token.Credentials can be either simple username/password or can be SSL certificates. SSL certificates uses the OAUTH protocol and are more secure.
You can design your URI like this-
URI for token request-> http://myservice/some-directory/token?
(You can pass Credentilals in this URI for Token)
To use this token for resource access you can add this [Authorization:Bearer (token)] to your http header.
This token can be utilized by the customer to access different component of your service layer. You can also change the expiry period of this token to prevent misuse.
For your second question one thing you can do is that you grant different token to access different resource components of your service layer. For this you can specify resource parameter in your token, and grand permission based on this field.
You can also follow these links for more information-
http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
I have faced the same problem before. Login does not translate nicely to resource based design.
The way I usually handle it is by having Login resource and passing username and password on the parameter string, basically doing
GET on http://myservice/login?u={username}&p={password}
The response is some kind of session or auth string that can then be passed to other APIs for validation.
An alternative to doing GET on the login resource is doing a POST, REST purists will probably not like me now :), and passing in the creds in the body. The response would be the same.

Django: Is there a safe and robust way to allow account-holders to have separate domains on your app?

If I want my account holders to be able to have their own sub-domains and even their own domains altogether. Using NGINX as my proxy server, should I create domains for each one in my NGINX conf and have my clients point their domains there or is there reasons why this would be bad? Also, if I do that, how can I pass account-specific (account in Django DB) information in with the request (ie, request from www.spamfoosaccount.com to my server, so I proxy the request back to Apache, but how does my application know that it came from spamfoo's account unless I look at request.HTTP_HOST (which might be the best way, but I don't know until I ask). Thanks in advance.
To know from which domain a request is coming from, you have to use request.META["HTTP_HOST"].
However, do not rely on this value for authentication, it can be forged easily. Authentication should be done in the usual way with django.contrib.session. A request from a specific domain/subdomain should not have more privileges/rights, even when the request contains an authenticated session. Privileges should be given to users/groups of users, not to domains.
Note that browser sessions cannot cross second-level-domains (e.g. session cookie from foo.com wil not be sent to bar.com), it can however be a *.foo.com cookie for all subdomains (if you explicitly set it so).
Let your users point their DNS records to the IP of your server, let NGINX route the request based on the domain to your backend and do normal authentication in Django.
Your question:
how does my application know that it
came from spamfoo's account
I don't know the specifics of your application, but it shouldn't matter where the request came from, but who issued the request (e.g. an authenticated user). You should have a model/field that links your users to their respective domains. When a user is linked to only one domain, the application should assume the user came from that domain. When a user is connected to more than one domain, you can look at request.META["HTTP_HOST"]. If this value matches any of the domains, the user is linked to, it's alright, the value may be forged, but by a user that is linked to that domain nonetheless.