I've written my own login app to protect my api following the oauth-login-app example.
I've implemented the web server flow and everything works great.
My question is: how should I handle an authentication failure at step 3? How do I tell he client app that the authentication failed? The user could either press the cancel button, or refuse permission or just enter the wrong details.
When you initiate OAuth 2.0 (dance) with
/authorize
the user-agent land on /login page (created/hosted by you),
post redirect.
enduser(user-agent) submits the username/password
to the page hosted by you. Here you collect the credentials and
submit to Apigee, and if authentication fails, send a HTTP 401
response. Now your application should be in position to re-render
the login page and with a flash "invalid credential".
Now coming to if user is authenticated but rejects the authorization request in
consent page, you should redirect to the "redirect_uri" provided
by client, with error code.
How do I tell he client app that the authentication failed?
The login app will redirect the control back to the application redirect URI - with added error code/description in the URL as hash parameters. In case of success the URL is appended with code or token.
You can do this redirect from your login app directly but I would suggest to make the redirect call first to an Apigee Proxy and let Apigee Proxy send the redirect back to app. Both in case of success and failure. In this way you will have the benefit of using Apigee analytics that helps your understand how many OAuths failed for what reason etc.
EDIT:
You can use the same GenerateAuthorizationCode proxy you have built for the success flow. When login fails or succeeds, in either case you need to pass that information to this proxy. Generally the login app and this proxy should share this information using a common session store. You can not pass this information just using a redirect parameter because that can be changed by the client user agent. When you redirect to the GenerateAuthorizationCode redirect proxy, do so by appending a random session ID in the URL. That id can be used by the GenerateAuthorizationCode proxy to look up the login status from the session store. Then you can either send back a redirect with error or a proper oauth code based on if the login was successful. An easy implementation of the session store can be done using a distributed caching resource in the apigee gateway. Login app can put/get the session using an internal API. While the proxy can use policies to retrieve the session information.
Related
I'm developping a webapp linked to a CAS server with phpCAS. Up to now everything was going well, I was able to access my app after the CAS authentication. I'm now supposed to implement a logout feature : when someone logs out of the CAS server, it sends logout request to all apps opened for that session.
The problem is my app doesn't seem to receive that request. I contacted the adminstrator who told me that he can see the request leaving the server. He then asked me to confirm him that my server received that request.
And here is the problem : I have no idea how to see if the server received the logout request (a json file...apparently a POST Method is used to send the data to the address of my app...as you see, I have no idea what I'm talking about.). I've been searching for days now and I'm totally in the dark. I tried to use tcpdump. I see a TCP F Flag when I logout of the CAS server so it seemed first like a good thing. But I have no idea how to see if my server has received a logout request.
Hoping that someone can help me...
Thanking you in advance.
And here is the problem : I have no idea how to see if the server received the logout request
You need to design some kind of filter/interceptor that sits in front of your application and intercepts all requests. This filter should examine the request body to see if the request is indeed a logout request. If it is, parse and consume the request body and begin to logout and remove the application session accordingly.
...with a little bit of searching and effort, it looks like phpCAS can handle logout requests on its own:
https://github.com/apereo/phpCAS/blob/master/docs/examples/example_logout.php
apparently a POST Method is used to send the data to the address of my app
Not "apparently"; rather, exactly. According to the docs:
The CAS Server MAY support Single Logout (SLO). SLO means that the user gets logged out not only from the CAS Server, but also from all visited CAS client applications. If SLO is supported by the CAS Server, the CAS Server MUST send a HTTP POST request containing a logout XML document (see Appendix C) to all service URLs provided to CAS during this CAS session whenever a Ticket Granting Ticket is explicitly expired by the user (e.g. during logout). CAS Clients that do not support the SLO POST requests MUST ignore these requests. SLO requests MAY also be initiated by the CAS Server upon TGT idle timeout.
And then here is the actual payload.
I'm having difficulty using Nginx's http_auth_request_module with dynamic, user specific URLs.
http://nginx.org/en/docs/http/ngx_http_auth_request_module.html
I need to authenticate (using OAuth 2) a user whenever they attempt to access their notifications. I've got an Nginx instance acting as a reverse proxy to an API (api.*) built on Django, and a Node server (notifications.*) for real-time notifications.
Assuming I can authorize requests (return 200 on success, 403 on failure) through my API at:
api.example.com/authorize/user_id/ 'Authorization:Bearer user_access_token'
And the user's request is:
notifications.example.com/user_id/ 'Authorization:Bearer user_access_token'
How would I dynamically take the user's request to the notifications subdomain, proxy it (including user ID & access token) to my API to authenticate, then continue proxying to notifications iff the user is authorized?
I think the problem really comes down to how do I dynamically set the auth_request URL with the request's user ID and access token. Any help would be greatly appreciated!
I have a frontend (SPA, angular2, lite-server) and a hidden backend (not exposed to public, i.e. localhost:8080, spring boot+spring security), frontend can access backend by proxying frontend/api calls to backend/api under the hood.
Basically, the steps for this kind of OAuth2 flow are:
On UI - hit url to authorization server with redirect_uri specified
Authorize
Get back to redirect_uri with access code
???
Server exchanges access code for an authorization token and keeps it
User(authenticated) gets back to the page he was restricted to access
I can't get the steps between 3 and 5. As my backend server is invisible, the redirect_uri should be the one in the frontend. I could possibly use a frontend/api/auth which will proxy the call to backend/api/auth and backend will succesfully get the authorization grant however in this case user won't be redirected back to a frontend. So, should I get the code in the javascript and do a POST to /api/auth from the javascript instead?
Also I don't get how to get back to step 6 after that as after all redirects SPA app will be reloaded(dropping the state) and redirect_uri is an url to /api/auth.
If I get the question right, the easiest would be to "expose" the server via localtunnel or ngrok.
I'm writing a web application which requires a user login. As you might recognise there are many workflows for responding on invalid user credentials. Most browsers are captable of storing (accepted) user credentails in their credential storage.
My original question splits up into two parts:
Which HTTP status code should be send to the user if a site requires a logged in user? I don't mean the situation the user is requesting the login page by herself.
Which HTTP status code should be send to the user if he/she has entered invalid credentials?
HTTP 401 is only for the "old style" authentification via browser prompts I guess. I'm using my own login pages to get rid of those browser prompts.
There are many standards for the authentication. Couple of example you can find here:
http://docs.oracle.com/javaee/1.4/tutorial/doc/Security5.html
The error code 401 you described is used for the Basic Authentication. It is not old :).
When you use your own login form please follow the standard Form authentication flow:
If a user access a protected resource without an authentication redirect to a login page (HTTP code 302)
Show the login page (HTTP code 200). Submit a user name to a dedicated URL (generally it is j_security_check)
After a successful authentication redirect back to the original protected resource (HTTP code 302)
After a failed authentication show once again to the login page with the error code (HTTP code 200)
If a user access a protected resource after the authentication show the resource (HTTP code 200)
To distinguish between an authenticated and not an authenticated session you can use HTTP cookie.
It is recommended to use GUID and not any user information (e.g. user name).
401 Unauthorized / 407 Proxy Authentication Required are the only status codes that are relevant.
401 Unauthorized should only be presented if you are denying access to any resource - NOT if you are redirecting or presenting them with a login page.
407 is just like 401 except you are expecting auth to be handled by an external service and you expect to be provided with a Proxy-Authenticate header field.
More typically, you are presenting the user with a 200 OK and a login page.
I know there has to be an obvious solution to this problem and I am missing it, so I would much appreciate someone enlightening me so I don't spin my wheels...
I am writing an ASP.Net application that will interact with a service API (Evernote specifically). Evernote requires OAuth for security and before I can actually interact with the objects I need to obtain a token.
The workflow goes like this (explaining it to myself as much as anyone else!):
Build a url with my development api key and secret key and some other OAuth stuff, send it to Evernote to request an access token.
Send the url as a request to Evernote and pull the new access token out of the response
Build another url with the access token to request an authentication token for the user. This url goes to a page the user must interact with to login (if they haven't already) and then authorize my application to access their account. The last param of the url I build is a callback url which will be called from Evernote's servers.
If all goes well, Evernote will request the callback url and include the new authentication token as a param.
Once my server receives the callback with the embedded token I can use it so that my app can interact with the users' notes on subsequent requests.
The problem is that I'm writing this app on a local box, not an ISP under a public domain. So my callback is to the localhost server. Of course, localhost is relative, so Evernote can't resolve my callback... I can't ever receive an authentication token and debug at the same time.
There has to be a way around this problem because this authentication model is not unique to Evernote (by a longshot... Flickr uses it as do a lot of other services). So can someone tell me how to set things up so I can get the authentication token and still be able to debug on my local box?
Help is much appreciated!
OAuth is quite tough to implement. It may not be the answer you're looking for, but this is how I managed to get the job done:
Write some code on my local dev machine.
Run a bat file (or alternatively hook a post-build event in VS) that executes a msbuild deploy script and deploys the application to a test server.
Run the application on the test server. After obtaining the request token and requesting for authorization it redirects to the Evernote website.
After successful authorization the Evernote website redirects back to my test server and the authorized request token is exchanged for an access token.
Instead of debugging (I don't have VS on the test server) I examine the logs of the application (the logging I used was as simple as writing to a text file).
Rinse and repeat
For the purposes of testing I registered a temporary public subdomain (e.g. testing.oauth.mydomain.com) so that Evernote will be able redirect to that url.
According to this (How do I develop against OAuth locally?) the callback is issued by the browser, so it should be able to hit localhost.