I've been trying to get Rails to play with the new Facebook Graph API. After I get the authorization "code", I need to send another request which returns the access token in JSON form.
It seems to work fine, however I want to fetch the access token JSON without redirecting the user. I'm attempting to use Net::HTTP.get, but I'm not sure how to use it to get a request body, or even if it's the right thing to use to begin with.
Can anyone give an example of performing an HTTP GET?
I've figured out how to do this, the problem was mainly with the fact that I needed an HTTPS connection.
Adapted from http://snippets.dzone.com/posts/show/788:
path = '/oauth/access_token?...'
http = Net::HTTP.new('graph.facebook.com', 443)
http.use_ssl = true
res = http.get(path, nil)
#access_token = res.body
Anyone specifically trying to use the Graph API, note that the value stored in #access_token is in the form of a params string, e.g. "access_token=xxxx&expires=1234".
I got around needing to parse this by just redirecting to another page and using that as the URL params, but there's probably a better way to do this.
SOA#1
However please note that it means that server have to be log onto facebook - while if browser is redirecting it is user who have to be log into server. Hence did your server set the permission?
You can pretend that you are the user. Bad Horrible idea (you have to store passwords in cleartext on you server).
You can use OAuth. Hence you should use OAuth gem instead of Net::HTTP. You will not avoid the redirection - it is part of authorisation process and user must say that he allows to access data (imagine what would be if anyone could access anyone data on facebook). Turorial on writing OAuth clients in rails.
Related
I'm a newbie to this stuff so downloaded the samples which is all fine and I thought I could see what was going on and what I needed to do. However, got a bit stuck for no obvious reason so I wondered if anyone could maybe give me some hints.
I'm trying to engineer Cognito authentication and identity into an old Apache Struts 1 legacy web application written in Java, so all the activity needs to be server-side. Using the Cognito https://xxx.auth.xxx.amazoncognito.com/login? URL I can successfully authenticate and get an auth code back using this URL providing my client id, redirect URI and response_type=code so all good thus far.
If I then create an HttpClient (as per the sample code in Github) and call the token URL https://xxx.auth.xxx.amazoncognito.com/oauth2/token and write various parameters to the request body (grant_type=authorization_code, client_id=as previously, redirect_uri=my URI and code=auth code just returned), I get an "unauthorized_client" message returned. But the code is valid albeit for authorization, and the client_id is correct because I used it previously.
My log:
Cognito following successful signin, continuing to url http:[redacted]/passport/CognitoHandlerSignIn.do?code=62eeb0b1-a76b-489b-bd28-e42023a497bd
(this was the /login succeeding)
Callback from Cognito received
(following is the log dump of the /oauth2/token URI called to)
Cognito token signin URL is https:[redacted].amazoncognito.com/oauth2/token
HTTP request header, added Authorization=Basic M29wcGR0azdpYzF2YjloNGd0OTQzNXYxcmI6MW9mMmFsaWNzZGR2dHZ1NmFkOHRuc2s4cnJ0cXEyYm0yc3RqbG1mcmkyamhkdXBubG1wMw==
HTTP request header, added Content-Type=application/x-www-form-urlencoded
HTTP request body, added grant_type=authorization_code
HTTP request body, added
redirect_uri=https%3A%2F%2F<redacted>%2Fpassport%2FCognitoHandlerSignIn.do
HTTP request body, added code=62eeb0b1-a76b-489b-bd28-e42023a497bd
HTTP request body, added client_id=[redacted]
HTTP request is sun.net.www.protocol.https.DelegateHttpsURLConnection:https:
[redacted].auth.eu-west-1.amazoncognito.com/oauth2/token
HTTP Json result=<{"error":"unauthorized_client"}>
org.json.JSONException: JSONObject not found.
at org.json.JSONObject.get(JSONObject.java:454)
at
What's wrong with this picture? I tried also adding client_id, code as URL parameters but I just get an "invalid_client" message instead.
I also tried using the /oauth2/token URI directly from the Struts app to provide a token but it returns the id_token using # rather than ? in the parameter list so it is client-side only and hence can't be intercepted by the Struts app and so will be a pain to forward to the server, but I could write some Javascript to do it if I had to. It doesn't seem the path of least resistance, though, as it seems wrong that the pure Java server side call doesn't work so I must be doing something wrong which isn't obvious to me.
I'm testing out RoR by building a Rails app with Pocket API, and I have to authorize the user. For HTTP requests, I'm using https://github.com/rest-client/rest-client library.
The first step, obtaining a request token works fine:
require 'rest_client'
response = RestClient.post 'https://getpocket.com/v3/oauth/request', :consumer_key => #consumer_key, :redirect_uri => #redirect_uri
#code = response.split("=")[1]
But I get a Bad Request error on the second step, which is to get an access token using the request token received on the step above:
access_token = RestClient.post 'https://getpocket.com/v3/oauth/authorize', :consumer_key => #consumer_key, :code => #code
400 Bad Request is what I get on Ruby application error screen. I have also tried the same request with cURL and POSTMan Chrome extension, and the status code I get then is: 403 Forbidden. X-Error Code I get is 158 which translates to X-Error message "User rejects code." on Pocket API docs: http://getpocket.com/developer/docs/authentication.
Since I have tried several different channels to test this request and failed each time, I'm guessing that the problem is not with parsing, but rather I might be missing an important detail or a step (maybe HTTP request headers?). Thanks for your help in advance!
Turns out that I (or we) have been missing an important detail:
Whenever testing out your request for Pocket API in POSTMan or anywhere else, we naturally skip the process of visiting the authorization URL which is in the form of:
https://getpocket.com/auth/authorize?request_token=YOUR_REQUEST_TOKEN&redirect_uri=YOUR_REDIRECT_URI
Now, even though you might have allowed your app to access your account before, on each call, Pocket API doesn't activate a request token before this URL is visited. Only then your request token becomes activated and can be used for 2nd authentication step. It works fine after doing that.
As a side note to anyone who is using Pocket API in Ruby on Rails, there is a nice wrapper gem for it: https://github.com/turadg/pocket-ruby
I can confirm that you are indeed missing HTTP headers, which will cause the Pocket server to reject the post request you're trying to send.
There are a few ways in which headers can be communicated: sometimes they are communicated through the codes/tokens associated with the server request (which here appears not to be the case). You need to use an "Authorization" header as per your doing this with OAuth with your initial request.
This should help you: notice the "Authorization:" header after the "Content-Type:" header contains the information that's returned.
For some in depth reading, go here.
I might also suggest trying the OAuth2 gem which does most of the requesting for you - it will probably simplify what you're doing quite a bit!!
Here's what it looks like on Postman.
We have a Rails application that is the API component running on api.domain.com and a front-end application in Ember.js running on www.domain.com.
When Ember.js sends a POST request to a route in the API, /events, we want the API to set a cookie to remember a unique user identifier.
Hence this method in the Events controller:
def set_tracking_cookie
cookies[:our_company_distinct] = {
value: create_identifier,
expires: 1.year.from_now,
domain: :all
}
end
As you see, the cookie is set on the entire domain, and is set to expire in a year.
The point is that the next time Ember queries the API, it will be able to read this cookie. However, this is not the case.
Each time the front-end queries the API, the API is unable to find the cookie, nor does it show in the cookies in my developer tools.
The Ember requests set the Access-Control-Allow-Credentials header to true, and I can confirm that the cookie is indeed sent in the response from the API with the correct values for domain, name, path, expiry, etc.
Am I missing something?
Thanks!
For anyone else going through a problem sending/receiving cookies in this way, here are some things I found helpful when I was debugging and ultimately fixed the problem:
When you use the Chrome's (or any other browser's) devtools, examine each request and check it to see if the cookie is being sent from the API on the request where you expect it to be sent, and if all subsequent requests from Ember (or whatever other JS framework for that matter) send this request. In Chrome, go to "Network > [request] > Cookies". Ensure that the front end is sending the cookie properly and that it indeed receives it properly.
We found that this was the best way of adding support for the CORS cookies to Ember was to be done like so: http://discuss.emberjs.com/t/ember-data-and-cors/3690
I am trying to make a GET request with AFNetworking to facebook's graph api. For various reasons, I'd rather not use the facebook SDK's native objects and would prefer to make those requests via AFNetworking. However, I'm a bit new to the networking side of things and I am unsure how to include the access token along with my GET request. Can anyone point me in the right direction?
I've tried setting the http header field to include this:
Authentication : {my access token}
but that doesn't seem to be working.
You need to add access_token as a URL query parameter for GET requests. See the docs here.
I have to implement a web site (MVC4/Single Page Application + knockout + Web.API) and I've been reading tons of articles and forums but I still can't figure out about some points in security/authentication and the way to go forward when securing the login page and the Web.API.
The site will run totally under SSL. Once the user logs on the first time, he/she will get an email with a link to confirm the register process. Password and a “salt” value will be stored encrypted in database, with no possibility to get password decrypted back. The API will be used just for this application.
I have some questions that I need to answer before to go any further:
Which method will be the best for my application in terms of security: Basic/ SimpleMembership? Any other possibilities?
The object Principal/IPrincipal is to be used just with Basic Authentication?
As far as I know, if I use SimpleMembership, because of the use of cookies, is this not breaking the RESTful paradigm? So if I build a REST Web.API, shouldn't I avoid to use SimpleMembership?
I was checking ThinkTecture.IdentityModel, with tokens. Is this a type of authentication like Basic, or Forms, or Auth, or it's something that can be added to the other authentication types?
Thank you.
Most likely this question will be closed as too localized. Even then, I will put in a few pointers. This is not an answer, but the comments section would be too small for this.
What method and how you authenticate is totally up to your subsystem. There is no one way that will work the best for everyone. A SPA is no different that any other application. You still will be giving access to certain resources based on authentication. That could be APIs, with a custom Authorization attribute, could be a header value, token based, who knows! Whatever you think is best.
I suggest you read more on this to understand how this works.
Use of cookies in no way states that it breaks REST. You will find ton of articles on this specific item itself. Cookies will be passed with your request, just the way you pass any specific information that the server needs in order for it to give you data. If sending cookies breaks REST, then sending parameters to your API should break REST too!
Now, a very common approach (and by no means the ONE AND ALL approach), is the use of a token based system for SPA. The reason though many, the easiest to explain would be that, your services (Web API or whatever) could be hosted separately and your client is working as CORS client. In which case, you authenticate in whatever form you choose, create a secure token and send it back to the client and every resource that needs an authenticated user, is checked against the token. The token will be sent as part of your header with every request. No token would result in a simple 401 (Unauthorized) or a invalid token could result in a 403 (Forbidden).
No one says an SPA needs to be all static HTML, with data binding, it could as well be your MVC site returning partials being loaded (something I have done in the past). As far as working with just HTML and JS (Durandal specifically), there are ways to secure even the client app. Ultimately, lock down the data from the server and route the client to the login screen the moment you receive a 401/403.
If your concern is more in the terms of XSS or request forging, there are ways to prevent that even with just HTML and JS (though not as easy as dropping anti-forgery token with MVC).
My two cents.
If you do "direct" authentication - meaning you can validate the passwords directly - you can use Basic Authentication.
I wrote about it here:
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
In addition you can consider using session tokens to get rid of the password on the client:
http://leastprivilege.com/2012/06/19/session-token-support-for-asp-net-web-api/