Grails: Lookup Domain By Other Property than Identity - web-services

I'm using Grails 2.4.3 for a RESTful backend and we are generating external ID's that are returned in the JSON, but keeping the generated ID secret. On a GET request like:
/users/123456
I have the show method like so:
def show(User user) {
respond user
}
The URL Mapping is simply:
"/users"(resources:"user")
Is there a way I can tell the User domain to lookup via user.findByExternalId rather than the id and keep the same code?

Related

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

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

How to check .AspNet.ApplicationCookie in application

I am developing an application in which users login in using different identity providers. Owin middleware create .AspNet.ApplicationCookies. I want to check whether it exist or not and its contains some data in it or not. How can I do this?
This cookie is encrypted by OWIN and is not easily accessible as a raw cookie data. However you can check if user is logged-in via HttpContext.Current.User.Identity.IsAuthenticated or just via User.Identity.IsAuthenticated if you are executing this in controller or a view.
If you put claims (that is the best way to add data into cookie) you can check list of claims for the currently logged user via ((ClaimsPrincipal)HttpContext.Current.User).Claims - this is basically a key-value list of strings. And name of identity provider will be stored there as well.

Multiple authentication providers (Database and Webservice) for Symfony 2

I need to implement an authentication for a Symfony 2 project with 2 user providers :
my project database ;
a third party webservice.
The process is quite simple : the user fills the authentication form with his username and password. Those info are first check against the user database and, if not found, the username and password are sent to a webservice that returns a 200 status code and a token if the user exists (another webservice will give me the user's role later).
Problem is, I should not add the users provided by the webservice to the database.
I first thought about using a custom UserProvider (http://symfony.com/doc/current/cookbook/security/custom_provider.html) but the method loadUserByUsername does not allow me to identify the user with it's password.
The solution I have in mind would be to create a user from the webservice to a temporary table, in order to identify the user from the database, but I'd rather implement a more elegant solution.
Any idea on how to do this the right way ?
The UserProvider let's you fetch a User object after the user is authenticated, the UserProvider won't authenticate the user itself. I think what you will need is a custom Authenticator using the SimplePreAuthenticatorInterface.
Here is a good explanation of how to do this: http://symfony.com/doc/master/cookbook/security/api_key_authentication.html
Essentially the Authenticator will be called by symfony and authenticates the user credentials against your webservice. On success the user object will be fetched and returned (finally using the custom UserProvider).

Django-Rest-Framework, update foreign key by ID when using HyperlinkedModelSerializer

This question is derived based on Django-Rest-Framework updating a foreign key BY Id.
I have a somewhat similar problem. I love HyperlinkedModelSerializer. I could navigate through all the links of the API from my web browser (e.g. Chrome, FF, etc.) but when I try to use the API, I have a much work to do in the client app. I have no issue with the GET request. In POST request when updating a model with ForeignKey, I need to construct the URL from the client app (e.g. AngularJS, Android, etc.) before making the POST request to the server. I'm aware of the ModelSerializer which solve the problem from the client app, but it is not navigable from the web browser.
I'm not sure what is a good approach in designing browsable REST API. I'm not sure how most people solve this problem, when they want to create a browsable REST API, at the same time, they don't want to add the complexity on the client app by having to parse the URL-ID before making POST request. Or could this be just my problem that no body encounter.
Why not HyperlinkedModelSerializer does the following instead.
return all the ForeignKey in URL upon GET request. So that developer could navigate the API from their web browser.
accepting ID upon POST request. So that developer could just pass the ID rather than having to construct the full URL from the client app.
Example:
c = Client()
data = {
'user': '1',
'industry': '1'
}
c.post('http://localhost:8000/favorite_industries/', json.dumps(data), 'application/json')
response = c.get('http://localhost:8000/favorite_industries/')
print(response.content)
# [{"id": 1, "user": "http://localhost:8000/users/1/", "industry": "http://localhost:8000/industries/1/"}]
Question:
What could be the advantage from the current design of HyperlinkedModelSerializer?
What could be the drawback from my suggestion?
How can it be done?
I don't see a need to construct URLs at all. When you are sending foreign keys, you are basically referencing another object. This other object you should already know its identifier. In your example, the user id is 1. If you build your API around HyperlinkedModelSerializer, user object will come with its own identifier: url. Before creating your favorite_industries object, you need to know which user to associate with. In normal situations you will have the user object including its url:
{
"url" : "http://localhost:8000/users/1",
"name": "Yeo"
}
All you need to do is sending this identifier as a foreign key:
data = {
'user': 'http://localhost:8000/users/1',
'industry': 'http://localhost:8000/industries/1'
}
I say in normal situations because usually in your client app ids are not entered by users but other info like name are displayed for the user to pick which mandates having the full user object including its url.

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.