How can I pass User Id back from Shopify's oAuth to my website? - rest

I am using Shopify's OAuth for developing a custom Shopify public app and the OAuth part is working fine. I have used the state parameter to include the user id in the nonce value and then capture the user id from there so that I know which user to save that access token for. However, this seems really hacky to me. What is the standard way of doing it, ie capturing user id(User is a "user" on my application backend. The user id is his id for my application, not his shopify user ID) in this case? I am making the application fully REST API based so I cannot use sessions here. What is the general approach?
Here's the Shopify documentation on OAuth implementation. https://help.shopify.com/en/api/getting-started/authentication/oauth
Any help would be appreciated!

If I understand the question correctly, I don't think there's a more efficient/secure/non-hacky way of doing this other than how you're currently doing it. Ultimately you'd have to send something to Shopify, that Shopify then turns around and send back to you.
I'm doing a similar thing using the state parameter, but I'm encrypting the value (security by obscurity?) when sending, and decrypting when received. In my case, it's not a user id I'm using but a session id.

Related

Spring boot REST token authorization and authentication best practices

What is the best practise for authorization and authentication of users in REST spring boot?
I am building web app with standard pages + REST API for mobile. I looked at many articles about Spring security and basically most of them goes with some sort of fitler approach that will allow or block REST calls. In my case, however, I have some auth logic based on who the user is. For example, there is a /update API that updates user information, and user can update himself, but cannot update other person.
Initially I thought to use next auth schema:
User calls auth API and pass name/password or cookie
System generates short life token, saves in it's database.
User get this token, updates his cookie (so JS in web application can read and use it)
When REST call is being make cookies are passed. At Controller, token is extracted, checked for expiration, query is done to database to validate token and get user id.
Based on user id, REST will be permited or blocked.
Is this the right approach to implement? I have a pretty big mess in my head after reading articles about spring boot security.
At least: session auth will not work for me (REST is stateless). I want to make auth for mobile device without storing login/password there.
Does it make sense to pass this token in the REST body itself? What in case of GET method?
Many thanks for sharing your knowledge.
Did you find a solution to your problem?
I have answered this problem elsewhere, if you are sure you won't want to open up the API to other developers/clients in the future (if you do then you should look at OAuth) then a simple token based solution will work.
Something basically along the lines of this:
Setup a standard html login page, that you can use for user login to the app
setup spring security to return a cookie on sucessful login with an authentication token
in your mobile app, embed a WebView (or equivalent) and load this login form - allow the user to login via that webview, on response grab the cookie and store the token (as mobile is generally single user, you can keep that pretty long to save mobile users having to keep logging in)
Add a security filter to the the REST API to authenticate against the token (from the mobile app pass the token in the header for example) - then you will be able to use normal spring authentication context for current users etc.
This approach is suggested by Google here: (EDIT: Google seems to have changed the page I originally read to be about using Google+ sign in and OAuth2.0 - I can't see a link to their general Mobile/API docs so here it is in the web archive :) )
I have also written up my implementation here:
Overview of the approach using Spring security
The code & details
Although this was really just an experiment/Proof of concept, it might be useful in your thinking.
Cookie approach seems perfect for the use case. Token can be tied up with user id. Filter can extract cookie and pass user id for example as header to apis - that should take care of GET...

Possible approach to secure a Rest API endpoints using Facebook OAuth

I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more.
I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app.
I want the API to be accessed only by my applications and only by authorized users.
I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email.
A possible scenario that I have in mind is:
The user logs-in on the web app using Facebook, the app is granted
permission to access the user Facebook information and receives an
access token.
The web app asks the API to confirm that this user
is actually registered on our system, sending the email and the
token received by Facebook.
The API verifies that the user
exists, it stores into the DB (or Redis) the username, the token and
a timestamp and then goes back to the client app.
Each time the
client app hits one of the API endpoint, it will have to provide the
username and the token, other than other info.
The API each time
verifies that the provided pair username/token matches the most
recent pair username/token stored into the DB (using the timestamp
to order), and that no more than 1 hour has passed since we stored
these info (again using the timestamp). If that's the case, the API
will process the request, otherwise will issue a 401 Unauthorized
response.
Does this make sense?
Does this approach have any macroscopic security hole that I'm missing?
One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens.
In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.
I think the better solution would be this:
Login via Facebook
Pass the Facebook AccessToken to the server (over SSL for the
android app, and for the web app just have it redirect to an API endpoint
after FB login)
Check the fb_access_token given, make sure its valid. Get user_id,email and cross-reference this with existing users to
see if its a new or old one.
Now, create a random, separate api_access_token that you give back to the webapp and android app. If you need Facebook for
anything other than login, store that fb_access_token and in your
DB associate it with the new api_access_token and your user_id.
For every call hereafter, send api_access_token to authenticate it. If you need the fb_access_token for getting more info, you can
do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the fb_access_token. If the api_access_token is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the fb_access_token. You also have more control over settings an expiration date, extending fb_access_tokens, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
I know I'm late to the party, but I'd like to add a visual representation of this process as I'm dealing with this problem right now (specifically in dealing with the communication between the mobile app and the web api by securing it with a 3rd party provider like facebook).
For simplicity, I haven't included error checks, this is mostly just to outline a reasonable approach. Also for simplicity, I haven't included Tommy's suggestion to only pass your own custom api token once the authorization flow is over, although I agree that this is probably a good approach.
Please feel free to criticize this approach though, and I'll update as necessary.
Also, in this scenario, "My App" refers to a mobile application.

realmId doesn't come from QBO through the OpenId workflow

We are trying to implement OpenId in our application to connect to QBO. As an example we use code supplied by Intuit
https://code.intuit.com/integration/viewvc/viewvc.cgi/IntuitAnywhere-.NET/HelloIntuitAnywhere/HelloIntuitAnywhere/OpenIdHandler.aspx.cs?root=intuitanywhere&system=exsy1003&view=markup
The problem is that realmId is null, basically it doesn't come from the Intuit login page back to our app. All other data comes OK like Name, email.
We define attribute as
fetch.Attributes.Add(new AttributeRequest(
"http://axschema.org/intuit/realmId", true, 1));
I read that it was in bug in Intuit with regards to setting some cookies. Is it a problem or I am just doing something wrong?
I can post more code if need, but it's pretty much as in example supplied by Intuit.
When the customer authorizes access to their data through the 3 legged Oauth flow, the realmid will be on the querystring of the call back url that you provide.
The openId workflow doesnt always result in a customer selecting a QuickBooks company.
After the openid flow, call the javascript function direct connect(), you will get the realm id in the oauth flow as mentioned above
thanks

Authenticating users in iPhone app

I'm developing an HTTP api for our web application. Initially, the primary consumer of the API will be an iPhone app we're developing, but I'm designing this with future uses in mind (such as mobile apps for other platforms). I'm trying to decide on the best way to authenticate users so they can access their accounts from the iPhone. I've got a design that I think works well, but I'm no security expert, so I figured it would be good to ask for feedback here.
The design of the user authentication has 3 primary goals:
Good user experience: We want to allow users to enter their credentials once, and remain logged in indefinitely, until they explicitly log out. I would have considered OAuth if not for the fact that the experience from an iPhone app is pretty awful, from what I've heard (i.e. it launches the login form in Safari, then tells the user to return to the app when authentication succeeds).
No need to store the user creds with the app: I always hate the idea of having the user's password stored in either plain text or symmetrically encrypted anywhere, so I don't want the app to have to store the password to pass it to the API for future API requests.
Security: We definitely don't need the intense security of a banking app, but I'd obviously like this to be secure.
Overall, the API is REST-inspired (i.e. treating URLs as resources, and using the HTTP methods and status codes semantically). Each request to the API must include two custom HTTP headers: an API Key (unique to each client app) and a unique device ID. The API requires all requests to be made using HTTPS, so that the headers and body are encrypted.
Current strategy:
My plan is to have an api_sessions table in my database. It has a unique constraint on the API key and unique device ID (so that a device may only be logged into a single user account through a given app) as well as a foreign key to the users table.
The API will have a login endpoint, which receives the username/password and, if they match an account, logs the user in, creating an api_sessions record for the given API key and device id. Future API requests will look up the api_session using the API key and device id, and, if a record is found, treat the request as being logged in under the user account referenced by the api_session record.
There will also be a logout API endpoint, which deletes the record from the api_sessions table.
Does anyone see any obvious security holes in this?
I agree with the oAuth comments - you can of course make oAuth work nicely on an iPhone - the UX is totally up to you. There are mechanisms (jQuery) to pull back the PIN from oAuth and use it (without the user re-typing the PIN into the app). That reduces the UX to
1) Display web page (in embedded control)
2) user enters user and password and presses button
3) oAuth response page is parsed automatically.
This twitter oAuth implmentation does that http://github.com/bengottlieb/Twitter-OAuth-iPhone using a pre-existing oAuth library.
However, back to your original question. That looks fine. The only item you don't mention, is that you need to provide a mechanism on the web app to allow the user to logout/deauthorize a device session (in case they have lost their device).

How to make a specific web page inaccessible, except to those who get there by a redirect

I have a webpage on a Joomla based website that I am trying to make inaccessible to anyone but those who have been redirected there through a redirect page.
Basically, they would purchase something on a form on my page which is integrated with Paypal, and when Paypal payment is complete I have them redirected to this specific page. I don't want anyone to be able to just copy this url and be able to come back to the page later. Is there a way to do this?
Then you have to store some "token" in your database, which is invalidated after the first time a returning client accesses your "thank you" page.
The token should be given to the client (in the URL) when you redirect him to Paypal and when he comes back after a valid payment, the token must still be in URL.
As far as I remember from the time I tried to use PayPal in one of my projects, it is possible to pass something like this to Paypal and get it back.
Checking a redirect is a poor way to do this. Such things can be easily spoofed. Instead have the pages you require a redirect from to create a session record of some kind and pass the ID of that record in the query string to the restricted page. The restricted page can deny if the session ID does not exist in the database or is too old.
It's been a while since I worked with Joomla. You might be able to look at the Server variables and check the Referring URL. If it's not one of your web pages or paypal, then you can redirect the user to the page of your choice.
I would include a specific token on the redirect. Maybe a Guid that has a limited life and is assigned to that specific user.
Paypal has a feature called Express Checkout that does just what you're looking for.
If you only care that the link expires shortly after it is used, then I think you should create a one-time URL for the content you are trying to protect. Have the action of purchasing create a unique key or token, store the value of the token on your server, and then reference that token in your link:
example.com/purchased_content?token=59803475203658902345089
When the link is clicked, check against your stored values. You can expire them based on whatever criteria you want.
If you also want to prevent copying the URL to somewhere else, you can have the action of purchasing set a cookie with the token value. Then check the cookie when the link is clicked. This is not foolproof since a knowledgeable user can copy the cookie too.