I have a stateful php web application made in Symfony that uses cookies to keep alive the session of the logged user in the application(I have worked always like that, I'm really new in REST services).
I'm making a REST API using the business logic of this web application, so I can use it in different environments (Android at the moment).
In order to keep private the API, I follow the symfony cookbook(http://symfony.com/doc/current/cookbook/security/api_key_authentication.html), so the requests are served through a 'apikey' sent in header of every request.
At the moment, this 'apikey' is a dummy string hardcoded in my android code.
What I first thought to do with this 'apikey' is a login screen in Android that send to the API an user and password, those credential will be checked on the server side and if they are correct, send to the client a 'apikey'(based on those credentials) and then, somehow, store it in the client and then send it in header of every request of the API.
I'm misunderstanding something with this 'apikey' method? (probably yes, while I'm writting this it seems to me that this apikey is a more 'static' concept).
Isn't this idea a kind of 'stateful' that is against REST pattern? I mean, I keep stored something that is checked on every request.
What I want to achieve is to have a login in Android, check credentials in server side and then(if this check is ok) let the android app make calls to the API in a secure way...
How I should proceed then?
Thank you for your time!
I'm also learning such things with Android and Symfony. What i've come to understand is your API Key should be unique to every user, meaning that every user should have, as subscribed to your website, an API Key, which represents them. It will work like a unique login, except that using REST, you only need the API Key to be authentificated, instead of a login and a password.
In this case, your API Key should be hard to find. I guess you should use the user's ID and login, since they have to be both unique identifier, and make something out of it, like encrypting.
If you've learn more since, it'd be a pleasure to hear from you experience.
I've implemented the ApiKey "mode" in my Symfony web app.
From my perspective, after correct user connection (using login and password), you can generate a key resulting in the sha1 encryption of the concatation of any unique user info with the result of uniqid.
Related
I think it's important to say that I don't have any experience in the technologies nominated below, I have some idea what is going on, I've googled a lot, but still - more I google more dumb I feel. :)
Making an app in Ionic 2, users of this app can read/write data about themself in DB.
I am using Wordpress as backend, actually users will change values in the table that was created by some Wordpress plugin.
First problem - I have no experience at all.
Second one - I must understand which user is knocking to the server.
Because user can change only his own data in DB.
I've solved it by creating a script that checks GET request from app & that request has a param with user nickname, so I have turned this script to template and assignined it to the page. ( template was first thing that went to my mind, if you have better idea - please tell me how to do it better! ).
Well now I knew who it is, but I disliked that this so unsecure!
Its only GET request with user name in it and changes to bring into DB.
NOT GOOD.
I've thought that I should send not only nickname but also some kind of a password, so I can check if the user is actually genuine user, well, you know.
But knowing nothing about security, didn't know where to start so I've started googling.
I've find out that there is 'Basic Authentication' - disliked it because password is verry simple to decode (base64) and you must send it with every request (not safe).
Then I thought about crypting pass with strong algorithm like bcrypt & then send it with the request. Disliked it too - because at the end you are always send a password even if strongly crypted.
Now I've started to look in the direction of Auth 1.0
(because saw that wordpress has a plugin for it, I know little about wp however).
But after all I am not so sure that I am doing things in the right way.
I must finish many things, but I am stuck with this security issue and I don't know if it's my paranoia and there is simplier ways to accomplish what I want to do.
Don't have much time, don't want to waste time anymore.
Please, someone who is pro in this stuff give me an advise how to do this thing in the right way!
because I am going crazy with that stuff.
The best practice is to issue an access token from your server to your (or even third-party) client application by the following steps.
A user uses a client application.
The client application asks the user whether to use your service.
The user answers "yes".
The client application opens the authorization page of your service using a web browser. In other words, the client application makes an authorization request to your authorization server.
The authorization page explains to the user that the client application is requesting some permissions and asks the user whether to approve it or not.
The user inputs his/her ID and password into the login form in the authorization page and then presses the "approve" button.
Your authorization server authenticates the user and issues an access token to the client application.
The client application accesses a Web API of your service with the access token.
The Web API of your service checks whether the presented access token is valid or not.
If the access token is valid, the Web API returns a successful response to the client application.
RFC 6749 (The OAuth 2.0 Authorization Framework) defines 4 flows to issue an access token. Check the specification.
I am developing an Ionic App which consumes data from a Laravel 5 RESTful API. All the connections are protected (GET, POST, etc.) by username/pass and user roles, except the user creation.
My first doubt about security is to disallow connections from outside the App, avoiding thousand of user creations, overloading our server resources.
My idea is, when an user installs the app and opens it for the first time, to create a secret token which will be sent in every connection. Then check the device UUID and the secret token to ensure this is an authorized app.
What do you think of securing the connections this way? There is a better idea?
You need to look a JWT (Jot) JSON web tokens, they will solve the security issue. This can contain user id and other data like access level. Not things like security information or card information.
When a user authenticates Laravel sends them back a JWT which you store in local or session storage this replaces backend sessions.
It is generated by the backend using the parts that can be decrypted by the frontend and using a secret key to encryt the signature, if any of it is tampered with it will fail and deny access.
Every request angular will append the token to the header using a request interceptor and Laravel middleware will decrypt it and allow access to the route they need or return a error code '404' maybe.
If after install this authentication layer you can limit usage at user level on the backend.
But this should sort most of your issues, it a bit of a change in thinking but it does work and it solves a lot of sessions issues you get with ajax calls and it make load balancing easier because all server are looking for a token it can manage.
I was also encountering the same problems. But after search in google for a while I came to the conclusion that you can put up several walls against hacker, but for someone who is hell bend on hacking your app(ninja hacker) will find ways to use your app in malicious ways.
I also came across various ways you can protect your backend server(after google). These step generally make it difficult to use your app maliciously.
You can encrypt strings url using some algorithm and use encrypted string in program ie. https:\google.com\ is encrypted into something like \h09ae\hff00\hebab\h.... then in program String url ="\h09ae\hff00\hebab\h.." This way someone decompiling the app can't find your server backend url. In this case you need to decrypt the string url before you can use it.
Send sensitive data using HTTPS and inside the body of the request
You can verify if request is coming from the device by using google token. For this you will have to use Google API Console. Refer this link for proper android tutorial on this topic.
Lastly, sign key used when you create your apk is unique and ensure that your apk is not tampered with. So generate hash key of your sign key before it is upload to google play and save it in your server and programmatically get hash value of sign key and send it with very request to your backend.
Hope is helps you..
I'm currently building a web application which is an AngularJS frontend that communicates with a RESTful API built using Laravel. I'm making good progress, but finding it hard to get my head around how to handle user authentication.
I've been advised that I should be using OAuth for authentication, and I've decided to use it seen as it could be a learning experience for me as well. The package I'm using to handle this is oauth2-server-laravel.
The basic user story is that users can register their username/password combination for the application, and they then log into the application with that same username and password. They're only authenticated by their username and password, and not by any client secret. After login, they should be given an access token which will be send along with every future request to authenticate them on different API endpoints.
The OAuth2 library has a "password flow" grant type which seems to be what I need, however it also takes client_id and client_secret parameters, which I don't want. The request URI is something like this:
POST https://www.example.com/oauth/access_token?
grant_type=password&
client_id=the_client_id&
client_secret=the_client_secret&
username=the_username&
password=the_password&
scope=scope1,scope2&
state=123456789
But what I want is just:
POST https://www.example.com/oauth/access_token?
grant_type=password&
username=the_username&
password=the_password
How am I meant to provide a client ID and secret of a user that has yet to authenticate?
Is there a different grant I can be using, or is what I want to achieve just not suited for OAuth at all?
Take into account, that client id and client secret aren't parameters that you have to force your end-user to pass. They are static and defined in/for your client app (angular app in this case).
All you need to do is to create a record for your main app in oauth_clients table, and create a scope with full access in oauth_scopes table, and send this values when requesting token.
And that's all in fact.
Also, you may want to consider using implicit grant flow in case of building js-only application, because storing client secret and refresh token in a js app is insecure. Using implicit grant in a final product may look like login window on soundcloud and is more secure as the token is obtained server-side without exposing client secret.
Another way to go, if you still want to use password flow is creating a proxy for refreshing tokens. Proxy can hide your refresh token in encrypted http-only cookie, and your js-app don't ask your api for new token, but the proxy instead. Proxy reads refresh token from encrypted cookie, asks the api for new token and returns it. So the refresh token is never exposed. If you set token ttl for an hour let's say, then stealing a token would be quite "pointless*" in case of a normal application, and stealing refresh token would be "impossible*".
*Of course if someone really want he probably could hack it any way.
And yeah, i know this all looks a bit hacky - modal windows for logging in, proxy etc. But also searching on this topic i couldn't find any better and more elegant way of doing it. I think that's still a lack that all js-apps have to deal with if you want a token based authentication.
You are missing something with the OAuth specification. The client_id and client_secret are really important when asking for an access token when using the password method of OAuth v2. In fact, they are important for every method that gives you an access token. They identify the application or the server that has perform the request.
For example, let's say you have your API, 2 mobile applications and another server that do some tasks with your API. You will create 3 clients with their own client_id and client_secret. If your application has various access levels (they are called scopes in OAuth v2), the client_id corresponding to the other server will be able to call functions of your API that require the scope admin whereas your mobile application will only be able to call functions of your API that require the basic scope if you have defined scopes like this.
If your API grows up in the future, this is really essential. Another example, let's imagine you have given an API key (a pair client_id and client_secret) to one of your friend and he has build a nice mobile app with your API. If one day he starts doing naughty things with your API, you can't stop him very easily. Whereas you could have just removed his key pair if you had followed OAuth v2 principles.
OAuth v2 is not an easy thing to understand, take the time to read specifications and good tutorials before developing your API.
Some useful links :
The official RFC : https://www.rfc-editor.org/rfc/rfc6749
A tutorial on Tutsplus : http://code.tutsplus.com/articles/oauth-20-the-good-the-bad-the-ugly--net-33216
Just to add a bit to plunntic's excellent answer: remember "client" is not related to "user", so when I use a password flow I just define the client_id and client_secret as constants on the AngularJS app to tell the api backend: hey, this is the browser app that is being used to request a token.
This is more of a procedure question question than a code fault one so please be kind if I have posted in the wrong place.
I have successfully authenticated a gplus user client-side so the browser is holding the google id ready for me to use. I now want to post some data to my website with that id as the user id but i want to protect it meaning I don't want just anyone with someone else's gplus id to be able to post to my web app (it has to be the authenticated user at that time).
Should I install the php serverside sdk and use that? If so how do i merge the client-side data with that?
Thanks
You're absolutely right about wanting to get the ID in a secure manner to make it hard to impersonate. There are two main options, both properties of the authResult object that comes back to the sign in callback:
Send the 'code' to the server. This is part of the OAuth 2.0 flow, and can be exchanged on the server side for an access token. From that you can make API calls as the user, and retrieve the user ID and other details. You can be confident who the user is, as only Google could have generated that code. This would involve using one of the client libraries to handle the token exchange.
Use the id_token. This is a base64 encoded blob of JSON which includes the user ID (and email address if you requested the 'email' scope). What makes it secure is that it includes a cryptographic signature, which the server can verify, so it cannot be created by someone other than Google. The id token can be used to get the user ID, and so can be used for looking up the user on the server, but doesn't give access to make API calls. The benefit is that it only requires up to date certificates for verification which don't change that often, so most calls require no further network traffic from the server to verify the user.
Which you use is up to you, but both will require some code on the server. In general, if you don't need to call any Google APIs from the server, or are concerned about maximum login performance then use the id_token. There's a bit more about that sort of architecture here: http://www.riskcompletefailure.com/2013/11/client-server-authentication-with-id.html
You can even combine the two. The first time a user signs in (when they see the consent screen) the code exchange will return not just an access token (for making calls), but also a long-lived refresh token, which you can store securely in a database. If you store that, you can use the id_token to look up the user quickly, but still use the refresh token to help with API access.
I am working on builing an API and application section on a social network so it will be something like myspace, facebook, hi5, friendster, netlog, and many other's have application section, they all use a REST server method and most of them will issue a api key and secret to each application developed. The person who builds the app will pass the api key and a user signature that is created with a hashing algorithm based on the user's ID who is using the app and the apps' API key. The applications code should set a cookie with some information like user id and signature and time. So on my server end the REST part should I just build the signature the same way the app does, check to make sure they are the same, if they are I send the correct data back. My concern is, how do I make sure a developer does not set a user's cookie to keep them authenticated for a long time, should I compare the time the users signature was created and if it is like a day old then I will send a bad response back from the REST?
When a user first add's an application from my main site, I will load the application site into an iframe and I will pass in user ID and other fields where I include the iframe so the application can use GET to initially get the information it needs to set it's cookie.
If you can help on this issue I would appreciate it, does it sound like I am in the right direction so far?
BTW I am using PHp/MySQL
I would store the token & user identifier that you pass back via the API in a database with a timestamp. When the user checks in via API to authenticate, check that timestamp and see if it is too old. If it is then pass back something like FALSE which would trigger some other command to make them re-authenticate into your system, which in turn would generate a new api token for the user to use.
Store a time() value in a session and every time the user does something check that time value to see if it's been longer than X minutes.