basic http auth in Clojure/Friend - clojure

I am trying to make a basic auth for an API in Clojure with friend.
Here is the login request :
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'user=myuser%40email.com&pass=super-secret-password' http://localhost:3000/login/
I am using compojure as well, but I'm not sure how to reuse the linked example. Here are the parts that I don't know how to change :
How do I replace the username/password fields with user/pass fields like in my curl request ? I am able to extract them from the raw request, but I don't know how to pass it to Friend (do I need to change the credential-fn?).
Replace the user atom with data from the database. I have a auth [email password] that returns true or false (fetching from the database and using bcrypt). I can also fetch the user role from the database. How do I use the database (specifically I use mongo/monger) instead of the user atom ?

You can provide a totally different credential-fn, or stick to the demo where credential-fn is implemented using cemerick.friend.credentials/bcrypt-credential-fn. Read the doc of bcrypt-credential-fn at https://github.com/cemerick/friend/blob/master/src/cemerick/friend/credentials.clj, it is quite long. It expects a load-credentials-fn that loads a user given a username string, then checks if the password matches. In the demo, the load-credentials-fn is a map in the users atom, but if you have a database you would want to provide a different load-credentials-fn function that would lookup the database, you don't want to load your users table in the map in the atom.

Related

Django: Send a Post Request Through Form to Another Server

I have a form on a template on my domain1 and want to send a POST request to domain2. I am using Django as the framework. I only want domain2 to accept requests from domain1 and domain2 (itself). However, I run into csrf problems.
You need a RESTful API. That's a very large topic and would be dumb/impossible to do the work for you here with the info I've been given, so here's a summary.
I suggest Django Rest Framework for making api's.
What the above means, is that when you want to do this sort of stuff (POST requests from other domains), you need a token. This is usually done with a Json Web Token. Also known as JWT's.
The process goes like this:
Get access token from other site to have permission to use the API from that site. Certain http headers, passwords, etc, are often included with this every single time data is exchanged.
Once you get a response giving you permission, you can now perform the type of request you want, with the data you want.
The data format for all this is USUALLY done with JSON. So you will have to import json, then json.dumps(obj) to turn it into valid json, and json.loads(obj) to turn your response into a python dictionary, so you can use it in your template, or wherever you want.
If you want to see an example of this, I recently made a free GoFundMe clone on my guthub. In the donate() view at the bottom, it uses the requests library, and shows how a JWT is obtained and used. You can see it there.

Flask JWT Token/ Payload - Return User Json

I understand that Flask JWT gives us the /auth endpoint. Once a user successfully logs in, an access token is assigned and the logged in user can be stored in Flask JWT's current_identity. What I'm wondering is can I also return the User Json back to my client in the same /auth endpoint? Or does it have to be a separate request?
This is for a mobile rest-api, using Flask-Restful. Right now, I have a user log in. The login route (/auth) returns the access token to the client, and then I use the token to get the User Json in a separate request, but I feel like I should be able to condense this into the same request.
Any tips are appreciated :)
IDEA:
Can I create an auth resource via flask-restful and specify exactly what I want it to return? (the token for the server and the user json to the client?)
Flask-JWT has been abandoned for quiet a while now. I would suggest checking out Flask-JWT-Extended instead as an alternative that is still actively maintained (full disclosure, I'm the author of that extension).
In Flask-JWT-Extended you create your own endpoint instead of having the extension create one for you, so you can return whatever data you want there. Here is an example of this in action: http://flask-jwt-extended.readthedocs.io/en/latest/basic_usage.html

API Key implementation on a Django backend

I'm implementing a simple API using a Django back-end and want to support access control using API keys.
As is the standard, the protocol will use a combination of a private key and a public identifier to authenticate the request. The public identifier, data and hash(data+private key) will be sent to the server. The server will then duplicate the hashing function using the private key stored in the database and if the hashes match then the request is authenticated.
My question is regarding the 'data' portion. Of course, the client and the server need to agree on what 'data' is, otherwise the hashes won't match. The protocol can simply dictate that the 'data' is the raw query string as sent by the browser. In that case, how do I retrieve the raw query-string from the Django view (it parses it in a QueryDict thus losing the sequence information)?
Or are there any other best practices that I am missing?
You can always get the raw query data via request.body (or request.raw_post_data in versions before 1.4).

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 can an authentication key be passed to a restful web service?

Some existing web services I consume have methods that look something like this:
List<Employee> employees =
employeeService.GetEmployees(accessKey, allDepartments);
The accessKey serves two purposes; it acts as both authentication and identification. Only valid access codes are responded to (authentication) and it services as a link to a particular client's data.
If the services were to be done a restful manner I'm not sure how this would be achieved. I definitely would not want to do something like this:
http://www.business.com/<GuidHere>/Employees/
Since this would show the accessKey, which is somewhat secret, (ie, its usually in an encrypted file on the client which uses this) we can't show the GUID in a URI. How is something like this achieved using a restful architecture?
You could send the authentication token using HTTP headers.
If this is a RESTful web service I'm assuming it's being consumed by a machine so why not pass the access key in the url?
At then end of the day you need to put it somewhere and hiding them in hidden form fields in the browser (if the service is to be browsable) isn't much in the way of security.
If the key is so sensitive, why not symmetrically encrypt on the server per session and pass that value around instead?
Just some thoughts.
Kev
If time isn't an issue implementing OAuth security may be useful. OAuth uses a public key, and also a secret. The mess is hashed (in most cases) and the server will use the public key + it's copy of the secret to do the same hashing and make sure its result matches the requests.
The benefit is you wouldn't need to use HTTPS or POST. Get* REST api methods should be using the HTTP GET method (I'm not sure if being RESTful is your goal, just thought I would point that out). I agree with Mr. Pang, use http://www.business.com/employees. The query string could contain the list of department ids.
For your case the service call wouldn't have the 'accessKey' argument, rather it would become the public key (I imagine) and be used in either the headers, query string, or as a POST param.
Some good info on OAuth: http://www.hueniverse.com/hueniverse/
As Troy Alford pointed out, my original suggestion was incorrect. You shouldn't be using POST in a situation like this. You should use a GET request with the authentication information in the HTTP headers. Take a look at basic access authentication for one way to do that.