A quick question about API Keys with PHP/MYSQL. I have been doing a lot of reading over the last few days but just need further clarification and some best practice guidelines as I am only very new with HTML, JS, JQUERY, PHP / MYSQL.
My server side code is PHP, which connects to the MYSQL database. The database has a users table which will store columns such as id, username, password (which uses password_hash() via PHP5 so it does not store the plaintext value) and api_key. I will also look at adding some such as last_seen and last_login for further security.
I would like the API Key to be used to authenticate the user to access resources on the server (eg. parseID.php, which takes POST arguments to return a JSON result on the ID's the user enters). The user can use this API key in a script as well to access the JSON output if required.
My thought process is:
An already logged in user clicks a button to generate an API key.
The script generates an API key (Using password_hash()) and saves it against the user ID in the database
When a user wants to access a protected resource, they will provide the given API key in the GET/POST (or stored in a session??) which will attempt to match it with the one in the database and return the result (Auth VS Not Auth).
If authenticated, The User is able to access the resource.
I will also use SSL to encrypt the traffic between the user / resource.
I am a little unclear and wondering what other steps / best practices can be taken here to ensure that the API key and the users information is safe?
All of the information I have searched on here and on google is a few years old and using practices such as MD5 to encrypt the keys.
Thanks!
This is correct - the API key is assigned to the user and calls are required to pass the API in order to authenticate the user and check what they can do.
Some changes I'd suggest:
An already logged in user clicks a button to generate an API key.
If the user can only have one API key, it will be easier for you and users to just generate the API key when the account is created and make it available in their profile/settings area (i.e. make it a one-to-one relationship rather than one-to-zero-or-one). The only reason you'd want to generate it on demand is if you have to give explicit permission, e.g. through some moderation process.
Either way, you will also want to let users reset the API key (mainly in case of a possible leak).
BTW a more common pattern is to support multiple API keys. e.g. if you look at Twitter's developer dashboard, a user can create N "apps" and each app automatically gets its own API key. There are some advantages to this approach, e.g. you can gather metadata around the apps, API keys are partitioned (better security), permissioning models can be different for each app, and you can revoke a single app without affecting all usages. All that may be overkill for you though.
stored in a session??
Session is more of a web concept related to cookies being passed back and forth. You don't need that complication. It should be easy enough just to require the API key in every request path.
When a user wants to access a protected resource
You may as well require the API key in every request, not just those for protected resources. It should be just as easy for the user anyway, and it will let you do things like rate-limit and log requests on a per-user basis.
Related
I have a monolith web application powered by Laravel. Users access different forms and some of them have button on them that executes Ajax call to the back-end (example relative endpoint: api/external/get-current-temperature). A back-end function that handles the request than connects to an external service via API and obtain data, writes some log in database and pass data back to requestor (front-end user). But in order to execute any API call it has to authenticate and obtain a Token.
Question:
I have multiple users that can potentially request api/external/get-current-temperature at the same time. How should I handle authorization/token? Should I store it in database and check its expiration time before requesting a new one or what? How would I refresh it? - The external provide has no specific function that could be utilized to verify token. But I know for sure the token is valid 60 minutes.
The users of your application never have to be mixed up / mistaken with your foreign API. You can and should provide you own mechanism (i.e. tokens) to authenticate any users. If users are authenticated the external API is used, else an error-message could be provided by your application.
As users also fill several different form it's quite possible that you save some user-data. If every user has own authentication credentials it's easy and much more secure to provide only the user's own data. If you use for every user the same authentication token in your own application you might get the situation that one user can see data from another user.
So see it like this:
You / your application is the user of the external API, therefore you need only one authenticqation token for it. Your application users use the external API as a service and as that you should provide it in your app. The data though that are provided to the service might differ from user to user.
Example payment application:
The API is always the same, you as developer get an API key, but the payments are for every user of your application differently. As developer you might never even able to see, store or track the user-data that are exchanged between the foreign service and the user, but your app serves as hub and provides perhaps also some products or services that are considered in any payments.
I'm creating a TODO list application using Angular and PHP.
I use Auth0 to allow Facebook authentication and after the process completes the user is redirected to add TODO page. However, I'm confused on how to save that TODO item in my MySQL database. Which user ID should I use to save the TODO item?
I'm getting Facebook user ID in return; can I save it using the FB user ID?
You can, but if you use the Facebook ID as your internal way to identify users in your MySQL database you're making your application less flexible to change.
For example, you save the Facebook ID in a column with a data type that supports the Facebook ID format. Now imagine, that in two months you also want to support Google users.
The Google ID may be in a format that your chosen data type does not support, so you'll need to make changes. Additionally, it could even the case that Google and Facebook identifiers are not globally unique so the same identifier can be used by Google to represent user A while at Facebook it's used for user B.
Your best bet is to save the data in association with an internal identifier that you manage and them mapped it to a globally unique way to identify your users; for example an email address.
Given you are using Auth0 you can take advantage of the fact that it will provide you with a globally unique identifier for each user. This means you can later support new ways to authenticate your users and Auth0 will always provide your application with a globally unique ID, even in scenarios that users authenticate without having to provide email addresses.
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 designed APIs in php using SLIM framework. I can access these APIs like this:
http://192.168.1.210/getSchool
This API is used to get information about schools. I am using these APIs in my android application. Now I want to make security of my these APIs. so no one can access these APIs with out authentication means no one can get list of schools by just entering the above URL in address bar.
I want that user first log in using my android application then he or she can use my api, no one can directly access in my apis.
Please give me your valuable suggestion.
Thank you in advance.
Once a user is registered with your application, you can generate & assign them an API key in the database (perhaps a hash) which you can return to the phone. Each time the phone sends a request to the API it also sends across their API key which you can validate against their database entry.
This should also all be done over SSL to avoid MITM attacks/viewing of API keys.
There are also other methods available: Looking for suggestions for building a secure REST API within Ruby on Rails (language agnostic).
You should create UID and a secret key for each user when they sign up and store on the server. And pass these to the user using https initially. The user will store these two values(make sure secret key is kept safely).
When the user want to send a api request he will create the request url then hashes it using the secret key + timestamp and addes the UID, hash and timestamp to the request and sends to the server.
The server extract the UID then gets the secret from db and then generated the hash of the request (without UID, hash and timestamp) using secret key + timestamp param.
if the hash generated and the hash param from the url matches proceed with the request or ignore it.
Or
Implement OAuth
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.