Sending custom data via OAuth (specifically LinkedIn API) - ruby-on-rails

I'm using the LinkedIn API to authenticate users. After authentication LinkedIn posts data back to my app at /auth/linkedin/callback (as is the OAuth standard).
I also offer other auth methods (e.g. Google+, Twitter, etc..). If the user signs in with one of those, I want them to also be able to (on top of their existing auth) connect with LinkedIn to pull in additional data.
In those cases, I want the callback URL to be something different so I don't have to do some very custom if...then logic.
Is there a way to specify in an OAuth request where you want to call back to?
If #1 isn't possible, can I send some custom arbitrary data or flags with my initial request that are returned during the callback? That way when parsing the response I'll check those flags for the appropriate state of the User and redirect them as necessary.
Thanks!

The state parameter is guaranteed to be preserved across all interactions. You can store (encoded?) information in it, and when the final callback is called, you will get back the original value you sent.
A common use case is capturing the "end URL" for the user (like a deep link into your app that requires auth).
You are supposed to check that what you receive is exactly what you sent.

Related

Connecting Smartsheets with Celonis

i am trying to connect Smartsheet with Celonis. I already have a Client ID and Client Secret but everytime I try to connect both, Smartsheets shows an error saying Redirect URL ist missing or wrong. Thanks in advance
In the developter Settings of Smartsheet it asks for the APP URL and APP Redirect URL. I am currently still uncertain what to fill out in both fields.
As the App which wants to get the Data Sheet is Celonis, I have filled in an APP URL with the Celonis URL (something like -> https://xyz.celonis.cloud/package-manager/ui/studio/ui/assets/xxxyyy-11-123) and an APP redirect URL the Authorization Page URL (something like this -> https://app.smartsheet.com/b/autorize?form.....) and every other mixture of these and other URLs but nothing seems to work out.
I have also reviewed various Smartsheet Docs but found no answer until now.
First, registering an app in Smartsheet in the way that you’ve described is only necessary if your integration between Celonis and Smartsheet will use OAuth (i.e. Celonis will ask the user for permission to access their Smartsheet data and if approved by the user, then Celonis will be able to programmatically access the user’s Smartsheet data). Is this the functionality you’re trying to achieve?
If NOT (i.e. Celonis doesn’t need to make API calls as each specific user that connects to Celonis) — then you don’t need to register the app in Smartsheet. Just create an access token in Smartsheet for the app to use, and make sure the user (account) that owns the token has permissions to access the necessary sheets in Smartsheet.
If YES (you are trying to implement OAuth so that Celonis can access the Smartsheet data of the user that’s logged into Celonis)….then here’s some info about those two fields:
App URL is just the application’s main URL. For example, if I was implementing Smartsheet OAuth in my app where the home page was http://www.abctest123.com then that’s the value I’d enter in the App URL field when registering the app in Smartsheet. As far as I know, this field isn’t used for anything in the OAuth process — it’s purely for reference purposes.
App Redirect URL is the address of the page in your app where the user will be redirected after they choose Allow or Deny when they’re asked whether or not Celonis can access their Smartsheet data. This needs to be a valid page URL, for a page that you’re able to configure to read any query string parameters that are present in the URL — because when redirecting the user to that page, Smartsheet uses query string parameters to indicate whether the user allowed or denied access, and if they allowed access, to specify the authorization code and expiration info for that code.
If you need more info, the OAuth process is described very well in the Smartsheet Dev Docs: https://smartsheet.redoc.ly/#section/OAuth-Walkthrough.

How do I add a token to my request in Rails 4?

I have an upload application that will be accessible by multiple other applications. I want user security from those applications to be federated to this upload hub. I'm doing it with HTTP tokens that are shared between the applications.
I have read 5 different articles on how to secure an API in Rails. I have everything set up properly in the upload hub app. I have keys set up in my User table, and I have shared this key with the user table in the other apps. I have the code in place to check for this key, and to locate the appropriate subscription. Upon failure, the user is redirected to the login page of the source application.
There's just one thing. I can't find anywhere how to create the actual request! I want the users in the other applications to click an "upload" link that will take them to this application. No problem creating the link, of course. The problem is, how do I add the token to the request?
See, I'm not making programmatic requests to an API... The user is actually going from one app to another. I want the upload hub app to check the request and say "Oh, there's this big long key. Let me see if I can find a user associated with that. I'm obviously not going to put it in a query string.
The only thing I've come up with on my own is to have a bit of jQuery code that constructs a form with a hidden item containing the key in it, which it would get from a hidden field on the current page, then do a POST against the upload hub app. That's not really a token, but it's doable. Surely there's a better way?
UPDATE
I went the jQuery "postGo" route where I construct a form with a hidden field and send it as a parameter to the other app. I had forgotten about protect_from_forgery though. However, even after turning protect_from_forgery off, Rails somehow still strips all parameters except for controller and action from outside requests. Undocumented feature? Or maybe I missed the documentation.
Really, I just want SSO on a couple of apps. It looks like I'm going to have to create an Oath provider. Sure are a lot of hoops to jump through to federate a simple session on some apps that I own.
Here's a possible way of doing this.
In the upload controller method of the app, instead of redirecting the user directly, make a request to the upload hub app.
In the upload hub app, add a controller method and generate a token, store it and a user's credential in redis, or other storage of your choice, then response the app with the token.
Your app's upload controller method receive the response from upload hub, then give 302 response back to the client, with the token included in the redirect url.
The client redirects to the upload hub
The upload hub router accepts this format, the token can be in a query string.
Check in redis and find it by the token and match the user's credential

Google+ sign in session state

It isn't clear to me how the Google+ API platform deals with sessions. My web app uses the Google+ sign in button and after signing the person in I receive an authentication code that I can use for API calls. But the Google+ API docs don't indicate how to handle the sign in session from the server side. What they do mention is how to handle it in Javascript as outlined at:
https://developers.google.com/+/web/signin/session-state
They indicate to check the status.signed_in state which will be set to true if the user is signed in and then my client script is suppose to customize the UI accordingly. But that is nonsense for parts of the UI that require proof the user has signed in. A hacker could just as well put a breakpoint on the callback from Google's authentication, and change status.signed_in to true making the UI think the user is signed in. I need a way to verify on the server every time the page is reloaded to determine if the user is signed in. How am I suppose to do that?
how to handle it in Javascript as outlined at
The session state on the page you referenced refers to the state represented in the button.
From a server-side perspective, Google does not provide a state associated with users on a per-site basis.
A hacker could just as well put a breakpoint on the callback from Google's authentication, and change status.signed_in to true making the UI think the user
This would present the signed-in UI, but should not have access to actual user details.
The way that your site should probably be authorizing the user server-side is to validate an ID token or Access token that is securely passed from the client. All of the Google+ quickstarts show you how to do this and include instructions for getting started.

IOS application web-scraping dilemma

I have implemented a web-scraping iOS application for a service provider to get data usage information. This used to work fine using NSURLConnection to post the username and password to the site, and then scrape the response.
However, said service provider has recently upgraded their account website and the login step now also includes an account selection step. So you first provide a username and password, the response then includes a list of all your accounts. This is presented in a selectable list. Clicking an account causes another postback, the response is the data I want to scrape.
I am unsure how to programatically perform this second step, since no data is sent with the request, and no extra cookies are set. Each clickable account link causes a __dopostback javascript action, so it is all handled serverside. There seems no way for me to perform this postback using nsurlconnection as no data about which account was clicked is sent with the post.
Any ideas how I could get around this?

With Twitter oAuth authorization, how do you specify what twitter username?

Developing a web application that I've registered with Twitter. In this app, I might have 10 different Twitter Identities that I want to either Allow or Deny access for the application to.
For example:
https://api.twitter.com/oauth/authorize?oauth_token=XXXXXXXXXXXXXXXXXXXXXXXX&oauth_callback=http:://localhost:24649/TwitterIdentity/GetTwitterAuthorizationCallback/
It always just defaults to whatever my twitter account is logged in as and I have to specify Logout, then sign-in with new account. Its almost like I need an extra querystring parameter such as
https://api.twitter.com/oauth/authorize?oauth_token=XXXXXXXXXXXXXXXXXXXXXXXX&oauth_callback=http:://localhost:24649/TwitterIdentity/GetTwitterAuthorizationCallback/&ForUsername=billgates
Actually, you can pass in an extra parameter with the callback url, like so:
https://api.twitter.com/oauth/authorize?oauth_token=XXX&oauth_callback=http:://localhost:24649/TwitterIdentity/GetTwitterAuthorizationCallback?ForUsername=billgates
and the parameter will be sent back to you when Twitter calls the return url, like this:
http:://localhost:24649/TwitterIdentity/GetTwitterAuthorizationCallback?ForUsername=billgates&oauth_token=XXX&access_token=YYY
You can read more about this in the documentation - http://dev.twitter.com/pages/auth:
Always use an explicit oauth_callback
- It is recommended that you specify a default OAuth callback in your client
record, but explicitly declare your
oauth_callback on each request token
fetch request your application makes.
By dynamically setting your
oauth_callback, you can pass
additional state information back to
your application and control the
experience best.
Note that in the general scope of authorization, the authorized agent does not necessarily know the identity of the user on whose behalf it acts. In other words, there could be an implementation where your app can be authorized to read the Twitter stream of updates, while still not knowing which identity that stream belongs to. Adding the parameter you ask for would be information disclosure in this case, as your app will need a piece of information that the system is designed not to provide.
Or to put it in a real life example - imagine a valet parking, where instead of giving you a parking ticket and taking the keys to the car, the valet would ask you for your SSN just to park the car, just because the valet parks cars for other people too.

Resources