I'm writing an Android app which will authenticate itself using OAuth2 to a Web server under my control.
I'm using Apache Amber on the client side, and oauth2app with Django on the server side.
From the client, I can generate an authorization request, and start a browser Activity that goes to a page asking whether to allow the client access, and after answering in the affirmative, redirects to a page with a "code" parameter.
But how do I get the "code" back to my client, in order to make the subsequent access_token request?
Do I need to bypass the browser entirely? How would that work?
I believe you have a couple of choices here.
The redirect_uri parameter will indicate to the server where it should send the code.
From the ouath2app docs:
If a request is authorized, Authorizer:grant_response() will serialize an object into a JSON response will return a redirect response to the client’s redirect_uri with information on the authorization code passed as query string parameters (response_type CODE) or access token passed as URI fragments.
So armed with that:
If that value is a location on your server, then your mobile browser is going to get the value as part of the redirect. Specifically, you're trying to read the URI fragments in the redirect. I believe this is the intended usage for an application like yours. This blog post seems to have code that might be relevant, under the section "Retrieving the access token".
Alternatively, as you pointed out, you could send the token to a different handler on your server, and then pass it back to your client. It must the callback URL defined in the service.
I found a different blog post, specific to OAuth 2:
http://blog.doityourselfandroid.com/2011/08/06/oauth-2-0-flow-android/
The trick is to fire up a new Activity whose content is provided by a WebView (rather than a layout). You can attach a handler to the WebView that's called on the redirect to the page containing the "code" parameter.
Some of the specifics in the blog post concern Google APIs, but so far my experiments suggest that it will work in my situation.
Related
How can I setup PAW to work with Facebook locally for development? Or even at all for that matter?
I have a node.js backend that I'm setting up with Facebook Auth. Every one of my routes needs the user to be logged in. I have two endpoints related to FB Auth. localhost:3000/api/v1/loginFB and localhost:3000/api/v1/callbackFB. Both of these work great in a web browser.
loginFB simply returns this string... https://www.facebook.com/dialog/oauth?client_id=523534457345&redirect_uri=https://localhost:3000/api/v1/callbackFB&scope=email,public_profile,user_friends.
When I call that URI in a browser, it returns a code=blahblah which my callbackFB endpoint uses to fire off another request to get the access token. All good.
So now in PAW I'm confused by the difference between the request URI and the Authorization URL text field? Should I use the loginFB URI for my request URI? And then https://www.facebook.com/dialog/oauth in the Authorization URL textfield?
Basically what's happening is that when I click Get Access Token, it returns the code but my callbackFB endpoint 500's by saying "This authorization code has been used." The code that it's getting returned is definitely different each time I Get Access Token.
This is where I'm at with this thing (Client ID and Client Secret are actually my App ID and App Secret from fb's dev management site, and the Access Token URL is actually set to https://graph.facebook.com/v2.3/oauth/access_token which I'm 99% sure is the correct URI):
This is the error I get when I click Get Access Token button:
It would be awesome to get some advice from anyone with experience with this issue. Thanks.
Re: #MichaMazaheri
tl;dr Fixed in version 2.2.2
Sorry for the super late follow-up. We actually fix this exact issue in Paw 2.2.2, which is already released on our website, and pending review for the Mac App Store. (It was some JSON vs. Form URL-Encoded parsing issue). Thanks for reporting.
I am trying to build a Django powered website. I want the website to be dynamic. For example, I want the profile page for a authenticated user to contain multiple resources (like a friends list, a group list, usage history etc) and these resources should be loaded in the same area on the page by making API calls without reloading the page.
Here is my understanding of the process:
Browser on the client side requests the profile page at www.example.com/user:id
The server returns a HTTP response and sends the html, css and javascript to the browser.
To load variable resources on the webpage, for example, the friend list, the javascript makes API calls using HTTP and sending context in JSON.
The API returns a JSON response which contain the data requested.
Javascript renders the data as html and the client is able to see new content on the same page.
I thought that in order to do this, some of my server side views need to be ordinary Django views which returns an HTTP response, while some others need to be API views which return JSON.
Now here's my confusion. Let's say www.example.com/user:id is processed using an ordinary django view, while www.example.com/user/:id/friendslist is processed using an API view. Now if the user inadvertently points the browser at www.example.com/user/:id/friendslist by typing the entire URL and hits go, what happens?
If I go with the flow of logic that I mentioned above, then the view will simply return a JSON. No html, css or javascript. In this case, how will the browser know what html to display?
I am just a beginner and I am sure I got the flow of logic wrong. Can someone please point out which part I got wrong?
Now if the user inadvertently points the browser at www.example.com/user/:id/friendslist by typing the entire URL and hits go, what happens?
It depends on how you coded your server. In Django you can use is_ajax to check whether the request was AJAX or not. You could return an HTTP error code when the request is not an AJAX one, if you wanted. So a user who inadvertently points the browser to your URL but does not take any further action will get an error.
Note here that a knowledgeable user could circumvent is_ajax by setting the request header field HTTP_X_REQUESTED_WITH to XMLHttpRequest manually.
If I go with the flow of logic that I mentioned above, then the view will simply return a JSON. No html, css or javascript. In this case, how will the browser know what html to display?
Setting your returned data type to application/json already tells the browser what it is dealing with. The least a browser would do this with this is display it as text.
Here's an example of an API call that returns JSON: https://api.zotero.org/users/475425/collections/9KH9TNSJ/items?format=json My browser just shows the JSON.
I am trying to integrate SAML with ColdFusion 9 Enterprise. The problem I am facing is related to the SAML request I am doing. I am using CFLOCATION to make the request. When I am making the request the request to the server is made as GET request, and I SAML server expects it to be a POST request, which eventually ends up no matching the tokens sent from my server to SAML server.
I am not sure what is causing this. I also tried make the request using the CFHTTP making redirect = "yes" in this case it would not redirect to the url and would not give any error in firebug or in SAML tracer.
Can any one please help me?
eagerly waiting for a response.
Thank you :)
If the server receiving the SAML requires a POST, then a GET will not suffice, obviously. Since you are doing a <cflocation>, I'm assuming you're trying to redirect the user (and their browser) after building the SAML assertion to the screen.
You either have to:
a) Build your SAML as a form, and include Javascript to force the form to "post" (submit) after it shows on the page.... or
b) You can leave the form on the screen, typically with the SAML assertion embedded in a hidden field, probably named "samlResponse", and let the user click a Submit button to actually go.
YOU (the CF server) can't push the SAML for them. The user has to do it, either with an automated form post via Javascript or by allowing the user to submit the form manually.
Start there, report back.
Please VOTE TO CLOSE instead of downvoting. I can't delete the question now that there are answers for it.
I've been playing with JMeter a few days now and I'm starting to get into the steeper part of the learning curve it seems. I've added a login request (i had to put it in a Loop Controller in the Thread Group). I then have a cookie Manager followed by two requests that are made by the browser (according to fiddler) after logging in. These next two requests require a cookie though and they don't seem to be working right now. I've set the Cookie Manager to "compatibility" for Cookie Policy. Then I look at the view results tree and I see that the two requests after login are failing and in the Request tab I see "[no cookies]".
Rather perplexing. Here's a screenshot.
i've modified my login request a bit:
however the next request still fails with a "not logged in" and "forbidden" message:
Not sure as i don't have full test plan but your login request seems to have failed because you get a redirect from http to https in tree result.
As you can see in tree you have 2 samples inside
Login one with http then one i http.
I suggest if you are a beginer to read this :
http://jmeter.apache.org/usermanual/jmeter_proxy_step_by_step.pdf
It will help you build easily yoyr test plan.
I you don't succeed with proxy then I suggest you remove loop controller and test with only one iteration to see what's happening.
You can click on sampler in tree result and select request tab.
Check that your login request is using https, it's in scheme of http sampler.
If it's a redirect that you cannot anticipate, then disable follow redirect and with a regexp post processor:
http://jmeter.apache.org/usermanual/component_reference.html#Regular_Expression_Extractor
extract the url from the redirect and submit it with login and password in next http sampler.
Regards
I had to learn a little bit more about the requests being made to the system in order for this to work. Instead of a call to www.server.com/login, i made a request to www.server.com/sessions.json and provided a json file with username and password. doint this set the cookie and the cookie manager took over. Then without modifying the other two requests, everything was honky dory.
Based on the images that you have posted, I found the error.
Cookie manager should be under the scope "Test plan". You have created a Cookie manager with the scope HTTP request.
Please leave the HTTP Cookie Manager with the standard settings. It should work.
enter image description here
For more details refer to the below JMeter Documentation
http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Cookie_Manager
In my App I need to communicate with my Django website. Some resources require authentication so I need user login.
But this does not happen in a browser or a web view. I need to use Object-C to issue a login request and handle the response - basically to store the session ID I guess.
On the web server side, how should I do this in Django? To have a stand-alone view for that and return JSON maybe? How can I get the newly generated session ID though?
I wouldn't get the session ID. I believe logging in a user is more geared toward a web interface. I would create an API that serves the resources you need in your app. http://en.wikipedia.org/wiki/Representational_state_transfer Authentication would probably be best suited for a private/public key pair or some other similar popular api authentication system.
You don't need to make any changes to your authentication system, save for maybe making sure the login form is usable on the smaller screen. Cookies work the same on iOS as they do on the web. You can display a modal UIWebView with your login form. After the user logs in, presumably you are setting a session cookie. If you make a subsequent request to the domain the cookie matches, the cookie should be sent along. You want to look into the HTTP 'Accept' header field, which specifies the content type the client expects to receive. In your controller (view?), you'll want to check the 'Accept' header, and return the appropriate content type, probably 'application/json' (or a custom type for your API).