I have a Ruby on Rails backend web application. I use iOS application as a web client (WKWebView) written in swift. The authentication token is stored as a session cookies variable on the backend:
session['token'] = generate_token
The problem is that accidentally this session variable is lost and the flow is redirected to login page.
The WKWebView is not closed, just used to process HTTP requests.
I'm not able to figure out, why this accidentally happens.
Since you are using just a webView and not default Safari browser meaning you are making your custom browser hence you are responsible to handle things like caching your token for the current session. My suggestion, if you want the token to be stored and used only once then create a variable something like
let accessToken = "your json web token"
Then pass it as a header when making a request to your server.
If you want to maintain access then you might want to save your token in keyChain or userDefaults depending on the level of security.
Navigation and other user interactions
As I mentioned, using wkwebView meaning you are making your own browser so you have to detect subsequent requests as the user interact with your web pages. For navigation, you have to use WKNavigationDelegate methods.
If WKNavigationDelegate does not solve your problem then you have to make use of Javascript events ie.. post an event when user visit a certain page and use WKScriptMessageHandler to respond to those events by passing the acess token etc..
Related
I've a React JS app, which makes this request to my back-end API. i.e
window.location = "https://my-server.com" + "/gmail/add_account";
cannot set HTTP headers for window.location see this
this server endpoint redirects to Google OAuth page, which returns a response to my redirect_uri.
def add_account
# no auth headers sent here, because front-end has used window.location
gmail_service = GmailService.new
session[:uid] = params["uid"]
redirect_to gmail_service.generate_authorization_url()
end
def oauth_postback
# session object is {} here
# Since there are no authorization headers, I cannot identify my app's user
# How can I identify my app's user here?
end
The problem I'm facing is that when the OAuth flow sends the response to my redirect_uri it does not return include any authorization header, due to which I'm unable to identify which user of my app has launched this OAuth flow.
I've tried setting up a session variable in the /gmail/add_account endpoint, which works fine. After this endpoint redirects to the OAuth screen, and the Oauth flow sends a response to my Oauth redirect_uri, there my session object is {}.
How can I implement this flow such that I know which user has launched this OAuth flow?
You have basically two options:
the state parameter
The state parameter is part of the OAuth2 spec (and is supported by Google). It's a random string of characters that you add to the authorization URL (as a query parameter), and will be included when the user is redirected back to your site (as a query parameter). It's used for CSRF protection, and can also be used to identify a user. Be sure that if you use it, it's a one-time value (e.g. a random value that you store in your db, not the user's ID).
sessions with cookies
If the user has previously logged in, you should be able to identify them by their session cookie. It sounds like this is the approach you're currently taking, but the session is getting reset.
It's difficult to debug this without knowing more about your stack/code, but a good first step would be just trying to load your callback URL without the redirection to Google to see the session object is still empty. If so, that would indicate an issue with how you've implemented sessions generally and not something specific to this flow.
As a note, based on the code you've shared, I'm not sure how params["uid"] is getting set if you're doing a redirect without any query parameters or path parameters.
Finally, you may consider using a managed OAuth service for something like this, like Xkit, where I work. If you have a logged in user, you can use Xkit to connect to the user's Gmail account with one line of code, and retrieve their (always refreshed) access tokens anywhere else in your stack (backend, frontend, cloud functions) with one API call.
I have a web application which currently uses lighttpd with mod_auth and the htdigest method for authentication. I want to expand the web apps functionality to allow for 2FA. If I understand correctly, what happens for htdigest authentication is the following:
The browser requests a website from the server
The server responds with "authentication required"
The browser shows the user a window asking for username/password and sends this information to the server
The server serves the webpage
If I understand correctly, the server caches this auth info and automatically sends it for following requests.
Now, I want to add 2FA. I found out that I can use fastcgi to build a custom authorizer. Can I use this to do 2FA? How can I ask the browser to provide the user with a possibility to enter the OTP? It's no use to cache the OTP and send it with every request, so I guess I need to store a session token or something which the browser should send with every following request?
In my application, I have a screen where user clicks different types of files to view and download them. However this screen is only accessible after user is logged in through web site.
I launch the Safari browser with my URL by using this method:
UIApplication.sharedApplication().openURL(NSURL(string: url)!)
However, the user is being redirected to login screen because he is not authorized to use the website yet.
My question is, how to pass cookies or headers to Safari and launch the URL with those?
You can't do that directly. openURL does just that, no more.
You need to pass required credentials in the URL. The target server may read them from the URL and then set desired cookies in the response.
If you implement that, make sure it can't be abused to set arbitrary cookies or perform session fixation attack. One way to implement that securely is to use one-time identifiers:
In the iOS app contact the server using a valid auth cookie and ask for a one-time long random key, which the server needs to store for a while.
Redirect user to URL with ?key=<that one-time key>
Make the server verify that the key matches and set cookies for the user, and delete the key.
Be careful with passing any secure data in the URL query as it's considered to be a security risk.
Some reasons are:
URLs are stored in web server logs
URLs are stored in the browser history
URLs are passed in Referrer headers
Reference: https://blog.httpwatch.com/2009/02/20/how-secure-are-query-strings-over-https/
I know it's not what you are looking for, but more secure solution would be to use session level cookies together with WKWebView. Check this SO answer for more information https://stackoverflow.com/a/26577303/14009088
Is it possible to have a WinForms application make a simple call to an Mvc app over the wire to carry-out a simple query (into a controller > service > repository)? I'm wondering whether it should provide a service api controller, separate to the rest of the application which spits out the Json to the WinForms application, or should it go the WCF/WebService route?
It needs to be able to authenticate too so the end solution is secure. As the WinForms app needs to poll the end-point, I don't want to send the username/password in each request. Can there be some provision for a session on the end-point which times-out and then requires a re-login from the client?
Yes, you can use the System.Net.HttpWebRequest and System.Net.HttpWebResponse classes to create an HTTP client. See here for an example.
Web apps do have a session timeout which starts counting when there is no activity on a session. So, if you do not want to be re-authenticating on every request, you will need to echo the cookies that the server sends to you in HttpWebResponse back to the server with the next HttpWebRequest, so that the server knows your session and keeps you logged in. If you erase the cookies, you will need to re-authenticate. If you do not interact with the server for a while, (usually about 20 minutes,) you will also need to re-authenticate. (Assuming that your WinForms application will not check the 'remember me' checkbox on the login form.)
I'm using Flex 4(beta2) with Ruby on Rails 2.3.5 and using RubyAMF to transfer data back and forth between Flex and server.
I set up Authlogic on the Rails side for authentication.
I wasn't sure what's the best method to handle user sessions. I know this is done automatically with Rails by sending session id with cookie which Rails use to authenticate the user.
What do you suggest the best way to do this with Flex?
I thought of couple of options:
1. Manually fetching the cookie from the browser and then figuring our a way to send that to the server with every request I send.
2. Handling sessions expiration and flow on Flex side by manually expiring the session
Do you have other suggestion or recommendation?
Thanks,
Tam
Network requests in Flash use the browser networking stack so cookies in Flex work just like any other browser application. Usually authentication in Flex is no different than it is with a standard web application. Send credentials to the server which it correlates with a session id. Every subsequent request (RemoteObject, HTTPService, etc) also sends that session id.
We have seen that the flash plug-in propagates the session cookie when we do blazeDS (http) remote calls
In the past we have worked with BlaseDS and HTTPServices. In both the cases the request is sent to the server over HTTP. Our server stack as Java (JBoss to be specific).
We noticed that the flex client used to send the session information with the requests to the server. We used same information to store and fetch Principal on the server.
In one case, we propagated the token to the client. This was to avoid multiple submits for same requests - hence we used the common HTML submission approach of token generation where with every response carries with itself a new token and the client has to sent it back to the server for executing the next request.
For the session expiration, there is a good chance that a user is working on the client for any local needs and not working with the server which may have caused a expiration on the server without impacting the server. In this case, we disabled the session expiration on the server and wrote custom code to handle events - keyboard and mouse on the flex client. If the application was not used for a specified time, the flex client would expire both the sessions i.e. local and server
What do you suggest the best way to do this with Flex?
$loggedIn=Authenticate::isAuthenticated();
if(!$loggedIn)return false;
$user=Authenticate::getAuthUser();
First Authenticate the user and if he is logged in create the session. Include this in your every PHP or Ruby file, and check it. Send the Session ID to Flex to maintain the state and you set the time for your session to expire.
The above code does check, whether the user is authenticate to access the PHP or ruby class files.