Securing restful api calls - java

I have an application developed using AngularJS for front end and Java for back end.
issue i am facing is, if the user logs in to the application and searches for a particular data, there will be an API call with payload JSON sent to the server, in response we will get the data in JSON related to search parameters.
Problem here is user can open developer tool and copy the URL of the API and JSON payload and post the same data in Postman or DHC client and get the response JSON and more over he can alter data related to role and get search results that are related to other role/users.
My question is how to protect the API from directly calling form other sources and altering the payload.

There is no fundamental difference between requests sent by JavaScript client app by your browser and requests sent "manually" from any other tool like Postman or whatever. There is generally no security issue until all your requests are protected by any authentication mechanism like OAuth or simply with some secret API keys passed with each request (in this case these API keys should belong to the particular authenticated user only!).
Keep in mind, that security layer which protects your system from malicious or unsecured operations should lie on the server side only, not on client app. That means that everything which can be done from client app by a particular user can be done from any other tool (as you mentioned above) in "manual" mode by the same user.

Related

Is it possible to get authorization_code in OAuth 2.0 without web browser in Java?

As I understand, in authorization code flow we need to get authorization code and use it to get token after. We can get this code only when user confirms specified access. After that browser redirects us to redirect_uri and response will contain authorization code as parameter. So, the question: is it possible to get this authorization code without browser or any self made UI? Can we get it in application after correct request to, for example https://mysite.tuz/authorize ?
As you are using authorization code flow, the client requires a user agent (i.e browser or mobile app) to get the authorization code from the authorization server.
The whole purpose of using authorization code is that it can be passed via the user's web browser (user agent) instead of passing the access tokens directly via the web browser (user agent) which is not desired. Using authorization code,the Client then can directly retrieve an Access Token from the authorization server.
So the user agent is required to get the authorization code and act as an intermediary between client and authorization server.
If you do not require a browser then authorization code flow may not the correct choice. OAuth 2.0 supports several different grants i.e ways of retrieving an Access Token. Deciding which one is suited for your case depends mostly on your Client's type.
This might help you in deciding which flow to use
https://auth0.com/docs/api-auth/which-oauth-flow-to-use
You should use client credentials to obtain token without browser or any client. But if you need to use user credentials to get access token and id token of the user without browser or mobile app you need to implement you own client which will do the necessary logic for you and fetch the token for you. I already did it in java for the testing purpose. I don't know why you need to do it but you can implement your own client in almost any programming language . But in case you will decide to go this way you have to handle lot of things.
I expect your authorization server requires Proof-Key for Code
Exchange (PKCE) - so first of all before you start to communication
with server you have to create code verifier and code challenge
(google can help you with that :) in java it is quite simple)
Then you should start communication with server sending get request to url which ends with 'auth' you should send query params as: response_type (which is 'authorization_code' in your case), redirect_uri, client_id, code_verifier, code_challenge, scope, code_challenge_method (probably 'S256')
Then you receive I think two redirects from server so it is better to have some client in java which will automatically call those redirects. I used apache http client for my implementation. It has lot of features.
After successful redirect server will return login page to your client. It depends on authorization server but in this page you should put the data as username and password and submit the page. I have simply parsed the returned page and get the url for user authentication from it and simply make post request to that url with user credentials data sent in encoded form entity. In apache http client you will have all cookies from previous communication set (until you close the client) since apache http client automatically set all cookies returned in previous communication from server.
After make authentication request server will send you two redirects and you can store those redirects int http client context which you will provide for http client when you call authentication url.
In the last redirect there will be query parameter sent be server named "CODE" this is really important for you since you will use it to get token from the server
And finally you have to make one last post request to authorization server with url ended as token. So make a post request with GRANT_TYPE, REDIRECT_URI, CODE (you received in previous redirect), CLIENT_ID, CODE_VERIFIER (you have generated at the beginning);
Then authorization server will send you token and that's all

Suggestions for Authenticating between applications (Salesforce ->Heroku)

I have been struggling over the past week to get the ideal configuration for my implementation. Basically, I have a Salesforce Page which makes a REST callout containing some data to be computed, A Heroku server then computes this data before sending the computed data back to SF in the response. This all happens in the background and so no Heroku front end exists.
I want to protect this callout with oAuth2, but I'm not sure the best way to do it:
The data itself is not important, its the access to the heroku app which is.
If I use salesforce for authentication, it means that the callout structure doesn't work (I would have to implement a system for Heroku to grab the data from SF before returning it) which isn't ideal and I can't see a way to use Heroku authentication as it allows access to the api but not the app script in a single structure. I think I have to create my own authentication server within Heroku but I'm not exactly sure if this is the correct way of going about it.
Any tips would be greatly appreciated
This is my callout code from SF:
Http http = new Http();
HttpRequest request = new HttpRequest();
//Sets the url to heroku
request.setEndpoint('My App URL');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
//places the content into the body
request.setBody(content);
//Extends the read timeout
request.setTimeout('120000');
//Sends the request and waits for a response
HttpResponse response;
response = http.send(request);
Heroku Side:
post("/", (req, res) -> {
//creates a local var for the JSON string
String data = req.body();
//--** The server then computes this data and calculates output
String computedData = compute(data);
return computedData;
});
I need a way of authenticating this type of connection, Thanks!!!
Did you read the Heroku guide to OAuth? It's pretty helpful. The flow would be:-
Salesforce app issues a redirect to your Heroku - GET https://id.heroku.com/oauth/authorize?client_id={client-id}&response_type=code&scope={scopes}&state={anti-forgery-token}
After user has authorized access there is a callback to your Salesforce app with an exchange token
You Salesforce app then needs to exchange the token for an Access token with your Heroku app with the relevant scopes to access the data at Salesforce
I'm not sure if this is what you want though since the whole point of OAuth is not authentication but authorization ie. the OAuth flow is not designed to identify the user, but to enable you client (Salesforce in this case) to access the user's resources held by the provider (your Heroku app in this case).
Since you want Authentication, not Authorization, there are a couple of approaches you could take depending on how much work you want to put in vs how secure it needs to be (you have to make a call on this).
Quick and dirty but not very secure
You could just check the referrer Header on Heroku and if the client is anything other than your Salesforce app then you return a 403 Forbidden or 401 Unauthorized. It's not very reliable since referrer is not overly reliable but its quick and straightforward if you do not have a great understanding of authentication and just want something quick and basic.
Send a client ID with each request
This could be a Header or be in the body of the request. For it to be secure though you will need to encrypt it since you say you do not want to use SSL/TLS. So you will need to encrypt/decrypt the client ID at each end.
A basic approach is to just use some symmetric key that you share between your client (Salesforce) and provider (Heroku) which you store securely within each app somewhere so that hackers cannot read it. You also share (and securely store) some ID string (ideally some long random hash).
The flow would go like this:-
Salesforce app takes the random ID string and uses the symmetric key to encrypt it. This is what you send in the request to your Heroku app.
Heroku app - on receiving an incoming request - reads the encrypted value. It then uses the symmetric key to decrypt it. Your Heroku app then compares the decrypted value passed in the request and the random ID string (it also has stored locally) and if they are the same you have some degree of confidence that the source of the request was your Salesforce app. If not you deny the request.
Authentication is a big subject, as is encryption. If you really need to protect the data and there is a risk of you being sued if you do not, then you need to do some more research. If the data is not sensitive (or particularly valuable to anyone else) and you are just trying to have some basic front gate which reduces other applications from exerting a load on your application then you could consider just checking the referrer as a first attempt.

Is it compulsory to register our web application on Google Apps before implementing OAuth?

I am developing a Java application that needs to access personal account Google Data of a user. The development is currently in netbeans on my localhost. I am implementing 3-legged OAuth. And while sending Grant request, it sends me Unauthorized Request Token and then redirects to Callback URL.
While trying to access Access Token, it gives me Error "Error Getting HTTP Response". Now, as per it given in Google Documentation, it is given that "If the application is not registered, Google uses the oauth_callback URL, if set; if it is not set, Google uses the string "anonymous"." Does it mean that I must register my application on Google Apps Engine before granting authorization & accessing request ? Please Help.
For reference : OAuth for Web Applications, OAuth in the Google Data Protocol Client Libraries
Based on your question, it's probably not the registration piece that's causing you trouble. It sounds like you just haven't implemented OAuth correctly — not that doing so is easy. The OAuth process is roughly as follows:
Get a request token. You must pass in a bunch of stuff that declares what kind of stuff you want access to and where you want Google to send the user when they're done granting you access to that data. This is where you pass in your consumer key, which you get by registering. The consumer key will be the string anonymous if you are developing an installed application (i.e., mobile app, desktop app, etc). This is a work-around; the alternative would be to embed your client secret or RSA private key within the application itself, which is a very, very bad idea. If you use 'anonymous', you should absolutely be setting the xoauth_displayname parameter. (Actually, everyone should set this parameter, but it's especially important if you're using anonymous.)
Once you have a request token, you then redirect the user to the special authorization endpoint, passing along the request token key in the query string. Assuming the user grants access, Google will redirect the user back to the callback URL that you associated with your request token. The request token is now authorized, but it can't be used directly just yet.
Once the request token is authorized, you can exchange it for an access token key/secret pair. The access token key/secret can then be used to sign requests for protected resources, such as the private data in the API you're trying to access.
For web applications, registering is almost always a good idea. It makes it much easier for users to manage their access tokens and revoke them if your application misbehaves or if they don't want you to have access anymore. If you don't register, your application will probably show up as a fairly scary-looking 'anonymous' in that list. It's really only installed applications that you wouldn't want to register for. You probably also want to register for an API key. An API key will dramatically increase your rate limit and it will also allow Google to get in touch with you if your application starts to malfunction.
I'd link to the OAuth docs, but you've already found them. Hope my explanation helps!
If you're developing on your local machine, you'll continue to get the same result as above.
For more interesting tests, then yes, you'll have to register your app and push it to the app engine.
Google will check if the domainname of the return-url is registered. You could also modify your dns/host-file to point the domain-name you're using to localhost.

Securing a REST API

I am in the middle of developing a PHP social media web application which will be supported by various web services each operating a REST API. Web services will probably be implemented in Java with MySQL data layer but the whole point of what I am trying to do is make it really easy to implement modules in different languages/data stores depending on what is approriate.
So for example when the user logs into the application via a login form the PHP code connects to a web service and POSTs the username and password to check if they should be authenticated. I would normally at this point start a session and store it in a session data store.
Another example could be if a user sends a private message to another user. The message would be POSTed to the private messaging web service which would take care of all the storage. Similarly the web service could be contacted to retrieve messages for a user.
Although I understand how to implement the REST web service in Java and make the connection to it in PHP I am totally unsure as to how to secure the data being passed and make sure that it is the users data being returned. If for example I want to get all of user As private messages how does the web service know to return that users. I could pass that users identifier as part of the GET url but then surely any old user could just figure out the GET url and use it to look up other peoples messages. I thought maybe I could pass over the session identifier and IP address which would allow me to check the session data store and make sure it is the correct user?
To secure the data that is important - like the username/password I thought I would just pass it over SSL.
Hope this explains my problem better.
Thanks
Take a look at HTTP Digest authentication. Most clients should support it, and it means the auth details can be passed securely with each request as part of the headers without interfering with the payload of the request itself.
I think requiring OAuth is a good choice. Your end users should appreciate that other websites don't need to ask usernames and passwords to access their data. As far as SSL, it's clearly worth doing if you can. You'll have to see if the performance trade-off is acceptable.
Keep in mind that your api must mimic the HTTP protocol.
Http is stateless, and by adding any Sessions or so, you're trying to fake an "Alwaysconnected" method.
With a LoginForm, it's like I'll have to send two requests for each calls ;)
These are basically 2 questions.
When privacy is a concern I'd go for the safest option: Serve data over SSL (via HTTPS).
As far as authentication is concerned, there are several possibilities. Basic over SSL is one of them, but a simple login form with a cookie can be another one. (ASP.Net Forms Authentication for example.) This all depends on how you want to implement your authentication mechanism.

Supplying credentials safely to a RESTFUL API

I've created a RESTful server app that sits and services requests at useful URLs such as www.site.com/get/someinfo. It's built in Spring.
However, these accesses are password protected. I'm now building a client app that will connect to this RESTful app and request data via a URL. How can I pass the credentials across? Currently, it just pops up the user/password box to the user, but I want the user to be able to type the username and password into a box on the client app, and have the client app give the credentials to the RESTful app when it requests data. The client is built using Struts.
Cheers
EDIT - I don't think I made the question clear enough. I'm already forcing HTTPS, my question is more, in-code, when I'm requesting data from www.site.com/get/someinfo, how do I pass my credentials alongside making the request?
You more or less have 3 choices:
HTTP Auth
Roll your own protocol, ideally HMAC challenge/response based
OAuth
OAuth is currently susceptible to a variation of a phishing attack, one that is largely undetectable to the target. As such I wouldn't recommend it until the protocol is modified.
OAuth should also be a lesson about how difficult it is to design secure protocols, and so I'm hesitant to reccomend the roll your own route.
That leaves HTTP auth, which is likely best if you can use it.
All that said, almost everything on the internet uses form based authentication, and many don't even bother with https for transport level security, so perhaps simply sending the password text in the clear is "good enough" for your purposes. Even still I'd encourage using https, as that at least reduces the dangers to a man in the middle attack.
If you can add HTTP headers to your requests you can just add the Authorization header:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
where you're using basic authentication and the QWxhZGRpbjpvcGVuIHNlc2FtZQ== bit is "username:password" base64 encoded (without the quotes). RFC 2617
Well, https has nothing to do with authentication, it's just transport-level encryption.
if you interact with an HTTP api, be it that it's https or not, and the dialog box pops up, it means its using HTTP authentication, either basic or digest. If your client instantiates an http client to read data from those "services", then you can pass those credentials when you instantiate the object.
If you use client-side script, XmlHttpRequest supports http authentication as well.
So in terms of code, how you pass the credentials to the RESTful services is dependent on the http client you're using (the object you instantiate to retrieve the data). You can simply collect such a username / password yourself from the client, and use it to call the other service.
look at existing solutions. In this case, oauth

Categories