googleapi_auth, how it really work? - google-api

I'm playing with Google Drive's API and I would know if I need to do the code bellow each time I need to use the API:
import "package:googleapis_auth/auth_browser.dart" as gauth;
import "package:googleapis/drive/v2.dart" as drive;
...
var clientid = new gauth.ClientId("xxx.apps.googleusercontent.com", null);
var scope = [drive.DriveApi.DriveScope];
gauth.createImplicitBrowserFlow(clientid, scope).then((gauth.BrowserOAuth2Flow flow) {
flow.clientViaUserConsent().then((gauth.AutoRefreshingAuthClient client) {
var drive_api = new drive.DriveApi(client);
// My code here.
}).catchError((e) => print(e));
});
...
Once client var generated, there is no way to recover it without to do these code lines each time?

I personally save the variable you called drive_api globally (in memory) and reuse it in my application (i.e. my webapp so yes it will run again when you reload the page). Some errors (I guess when the token needs to be refreshed, or if the permissions are revoked) might require you to re-run the whole flow. I think the trick is to run it "silently" after the page is loaded
flow.clientViaUserConsent(immediate: true)
by doing so, your "drive_api" variable will be loaded if the user already granted permission in previous sessions. For example I typically enable some buttons at this point
and if it fails (i sometimes add a "login button"), explicitly call (better do that on "on-click" to allow popup to appear)
flow.clientViaUserConsent()
Some doc for the immediate parameter:
/// If [immediate] is `true` there will be no user involvement. If the user
/// is either not logged in or has not already granted the application access,
/// a `UserConsentException` will be thrown.
///
/// If [immediate] is `false` the user might be asked to login (if he is not
/// already logged in) and might get asked to grant the application access
/// (if the application hasn't been granted access before).

Related

Lucee/ColdFusion - Locking session scope across a cluster and accessing session vars concurrently

This question applies to a Lucee 5.x application. I'm not sure if there are differences between how ACF and Lucee handle session scopes across a cluster.
Background: I'm implementing an autoLogin() function in application.cfc - in onRequestStart() - that looks for a token that's stored in a cookie, and then uses it to authenticate the user. Once a token has been used, it gets replaced with a new value, and the cookie is updated. When a token is not found or doesn't work, the cookie is deleted. A session lock is used to prevent multiple concurrent requests from attempting to login the user, which would have unintended side effects.
All the core functionality for this works (on a single node), but I need to make it cluster-friendly. The cluster is already setup correctly (this.sessionCluster = true; in application.cfc, along with a shared Memcached instance that stores session data), and it works fine.
The main questions I have are: (referencing the code below)
The code below uses an exclusive session lock to prevent concurrent requests from executing the login code at the same time. How would you replace the session lock below with one that locks the session across the whole cluster?
The code below assumes that changes to session variables can be seen immediately. Is this true when a session variable is changed on one node, and then a concurrent request on another node tries to access that same variable? If not, is there a way to refresh the session scope to ensure you're getting the latest?
Below is the autoLogin() function: (works on a single node)
private void function autoLogin () {
// multiple, concurrent requests could be hitting this on different nodes in the cluster
// if we're already logged in, nothing to do
if (session.isLoggedIn) {
return;
}
// get the auth token if it exists
var token = cookie.keyExists("auth") && isValid("uuid", cookie.auth) ? cookie.auth : "";
if (token == "") {
// if a token doesn't exists, nothing to do
return;
}
// assertion: user is not logged in and an auth token exists
// attempt to login using the token, but make sure that only one
// request does this at a time - wrap with an exclusive session lock
// lock the session - how would you do this on a cluster?
lock scope="session" type="exclusive" timeout="10" throwontimeout=false {
// check if logged in again - another thread may have succeeded while this
// thread was waiting for the lock to open
if (!session.loggedIn) {
// we can only call this once if user is not logged in!
application.auth.loginWithToken(authToken=token);
}
}
} // autoLogin()

Adobe Analytics - Force a session/userID refresh

We have a website that can be viwed from a kiosk in a shop.
When the inactivity is above 2 minutes, the site returns to the home.
Anyone knows how to refresh the session when this appens?
It could also serve make a refresh of the user id, but I don't know how it works.
I'm going to assume you are talking about Adobe Analytics javascript library and not the Android/iOS SDK, based on your tagging and lack of mention of it. If your kiosk is in fact using Android or iOS SDK, then please comment and I can update with instructions for that.
Adobe Analytics javascript library does not currently offer a direct method to force refresh an Adobe Analytics session/userID. However, you can effectively do it by explicitly setting s.visitorID yourself, which will override the default generated by the library.
So, when you want to start a new session, you can pop s.visitorID with for example the current timestamp:
s.visitorID = (new Date()).getTime().toString();
Or maybe you already have a "session" id you generate that you can use, instead.
Note: with this method, you must set s.visitorID (with the same value) for every hit for the duration of your session. So in practice, you would really do something more along the lines of generate the new value at start of session, put the value in a cookie, and put s.visitorID in s_doPlugin but it reads the cookie value.
Note: This will effectively make your visits and visitors metrics the same. Which is to be expected with a publicly shared device, but just mentioning it in case it comes up later.
pseudocode:
function startNewSession() {
// use whatever cookie writing utility you have to
// set a cookie named visitorID set to the generated
// value. In practice, the expiration doesn't really
// matter as long as it's something longer than
// your average session. Just setting it to default
// session expiration should be okay
var visitorID = (new Date()).getTime().toString();
setCookie('visitorID',visitorID);
}
// in your existing logic that times out returning
// home after 2 minutes of inactivity, call the function
// to generate a new id
startNewSession();
// this is AA's s_doPlugins callback function. This may look
// slightly different, maybe defined as s_doPlugins and then assigned
// to s.doPlugins, depending on what AA lib version you are using.
// This is AA's callback function that gets called whenever
// an s.t or s.tl call is made
s.usePlugins=true;
s.doPlugins=function(s) {
// make sure visitorID variable is addedto linkTrackVars
// so it gets 'registered' for s.tl calls.
s.linkTrackVars='visitorID';
// explicitly set the visitorID with the cookie, using
// whatever cookie reading utility you have.
s.visitorID=readCookie('visitorID');
}

Trigger function after session timeout or expire in laravel

Hello i'm kinda new to laravel and i have a question concerning authentication. I have the following function in my authentication controller:
public function signout()
{
// set logged in status to zero in database
$l = Login::where('user_id', Session::get('user')->user_id)
->where('logged_in', 1)->first();
$l->logged_in = 0;
if ($l->save())
{
// log user out
Auth::logout();
// Forget user session data
Session::forget('user');
// redirect user to login page
return Redirect::to('/account/signin');
}
}
Now in my session config, i have set sessions to expire after 60mins after which the user will obviously be logged out of the system. However that will occur without my other functions executing like setting user logged in status to zero in database or forgetting the user session array. Is there a way i can trigger those functions to execute after login session expire? Thank you in advance.
Update: I've been looking around again ever since i got a down vote for my question to see if there was already a solution to this, from reading the docs i got excited when i came to the "Events" section because i thought i had found a solution however i found out later on that there was no such thing as a "Session::expire" event in laravel, neither is there a function to check whether another user is logged in or not.
Your whole premise is wrong: sessions should have an expiry timestamp that's set when user logs in, and updated on every request if you want to have something like "session times out after 1h of inactivity".
Then you can basically:
Check if session is still valid when user performs a request, by checking the timestamp
Delete expired sessions using a scheduled task, so you keep things clean and tidy in the background
Anyway, if for some reason you end up needing to trigger some actions to happen when a user signs out Laravel actually has an Event that's triggered on user logout: 'auth.logout'

Most efficient way of authorizing users over different pages on my site?

I have only ever made single page webapps in the past; with these, as soon as a user connected, I would read the password hash stored in their cookies and match it to the value stored in my database to determine if the user was already logged in.
I am now wanting to make a site with multiple web pages though, and I have just realized that it would required querying the database every time a user goes to a new page; this seems extremely inefficient to me. Is there any better way to maintain an ongoing session with a client without straining my database/server in the process?
Take a look at using a session object Eg HttpContext.Session["UserAuth"] = true;
When you authenticate the user on your first page Eg Login, you can then create a session like in the example above. Then once you redirect to the next page, just check to see if the session does indeed exists and is valid.
Checking session:
if(HttpContext.Session["UserAuth"] != null)
{
if(HttpContxt.Session["UserAuth"].toString() == "true")
{
//Session is valid and user is logged in.
}
else{
//Session is invalid and user is not logged in.
}
}
So each page you want to check if the user is valid you can do the above check. As long as you have created the session on the first page at time of database authentication.
Please note the above code is just to give you an idea of how you can do this.
"UserAuth" is simply a the name you give to the Session that you are storing. It can be absolutely anything. The value you are storing in the Session in this case is 'true'.
So when you retrieve the value of the Session you simply get 'true', meaning the user is logged in.
When you log the user out for example you can change the value of the session "UserAuth" to false in the same manner in which you originally created it.
Eg
HttpContext.Session["UserAuth"] = false;

Go session variables?

I'm new to the Go language (Golang) and I'm writing a web-based application. I'd like to use session variables, like the kind in PHP (variables that are available from one page to the next and unique for a user session). Is there something like that in Go? If not, how would I go about implementing them myself? Or what alternatives methods are there?
You probably want to take a look at gorilla. It has session support as documented here.
Other than that or possibly one of the other web toolkits for go you would have to roll your own.
Possible solutions might be:
goroutine per user session to store session variables in memory.
store your variables in a session cookie.
use a database to store user session data.
I'll leave the implementation details of each of those to the reader.
Here's an alternative in case you just want session support without a complete web toolkit.
https://github.com/bpowers/seshcookie
Here's another alternative (disclosure: I'm the author):
https://github.com/icza/session
Quoting from its doc:
This package provides an easy-to-use, extensible and secure session implementation and management. Package documentation can be found and godoc.org:
https://godoc.org/github.com/icza/session
This is "just" an HTTP session implementation and management, you can use it as-is, or with any existing Go web toolkits and frameworks.
Overview
There are 3 key players in the package:
Session is the (HTTP) session interface. We can use it to store and retrieve constant and variable attributes from it.
Store is a session store interface which is responsible to store sessions and make them retrievable by their IDs at the server side.
Manager is a session manager interface which is responsible to acquire a Session from an (incoming) HTTP request, and to add a Session to an HTTP response to let the client know about the session. A Manager has a backing Store which is responsible to manage Session values at server side.
Players of this package are represented by interfaces, and various implementations are provided for all these players.
You are not bound by the provided implementations, feel free to provide your own implementations for any of the players.
Usage
Usage can't be simpler than this. To get the current session associated with the http.Request:
sess := session.Get(r)
if sess == nil {
// No session (yet)
} else {
// We have a session, use it
}
To create a new session (e.g. on a successful login) and add it to an http.ResponseWriter (to let the client know about the session):
sess := session.NewSession()
session.Add(sess, w)
Let's see a more advanced session creation: let's provide a constant attribute (for the lifetime of the session) and an initial, variable attribute:
sess := session.NewSessionOptions(&session.SessOptions{
CAttrs: map[string]interface{}{"UserName": userName},
Attrs: map[string]interface{}{"Count": 1},
})
And to access these attributes and change value of "Count":
userName := sess.CAttr("UserName")
count := sess.Attr("Count").(int) // Type assertion, you might wanna check if it succeeds
sess.SetAttr("Count", count+1) // Increment count
(Of course variable attributes can be added later on too with Session.SetAttr(), not just at session creation.)
To remove a session (e.g. on logout):
session.Remove(sess, w)
Check out the session demo application which shows all these in action.
Google App Engine support
The package provides support for Google App Engine (GAE) platform.
The documentation doesn't include it (due to the +build appengine build constraint), but here it is: gae_memcache_store.go
The implementation stores sessions in the Memcache and also saves sessions to the Datastore as a backup in case data would be removed from the Memcache. This behaviour is optional, Datastore can be disabled completely. You can also choose whether saving to Datastore happens synchronously (in the same goroutine) or asynchronously (in another goroutine), resulting in faster response times.
We can use NewMemcacheStore() and NewMemcacheStoreOptions() functions to create a session Store implementation which stores sessions in GAE's Memcache. Important to note that since accessing the Memcache relies on Appengine Context which is bound to an http.Request, the returned Store can only be used for the lifetime of a request! Note that the Store will automatically "flush" sessions accessed from it when the Store is closed, so it is very important to close the Store at the end of your request; this is usually done by closing the session manager to which you passed the store (preferably with the defer statement).
So in each request handling we have to create a new session manager using a new Store, and we can use the session manager to do session-related tasks, something like this:
ctx := appengine.NewContext(r)
sessmgr := session.NewCookieManager(session.NewMemcacheStore(ctx))
defer sessmgr.Close() // This will ensure changes made to the session are auto-saved
// in Memcache (and optionally in the Datastore).
sess := sessmgr.Get(r) // Get current session
if sess != nil {
// Session exists, do something with it.
ctx.Infof("Count: %v", sess.Attr("Count"))
} else {
// No session yet, let's create one and add it:
sess = session.NewSession()
sess.SetAttr("Count", 1)
sessmgr.Add(sess, w)
}
Expired sessions are not automatically removed from the Datastore. To remove expired sessions, the package provides a PurgeExpiredSessFromDSFunc() function which returns an http.HandlerFunc. It is recommended to register the returned handler function to a path which then can be defined as a cron job to be called periodically, e.g. in every 30 minutes or so (your choice). As cron handlers may run up to 10 minutes, the returned handler will stop at 8 minutes
to complete safely even if there are more expired, undeleted sessions. It can be registered like this:
http.HandleFunc("/demo/purge", session.PurgeExpiredSessFromDSFunc(""))
Check out the GAE session demo application which shows how it can be used.
cron.yaml file of the demo shows how a cron job can be defined to purge expired sessions.
Check out the GAE session demo application which shows how to use this in action.

Resources