I am using WebApp2 with auth for user sessions. My client will occasionally make nearly simultaneous requests to the server. The first one will make a request with session data that looks like this:
{
'cache_ts': 1408106895,
'token': u'GXpsaVQh5ZWtqxJMUBpGTr',
'user_id': 5690665774088192L,
'remember': 1,
'token_ts': 1408034938
}
Then after a call to auth.get_user_by_session(), the session comes back like this:
{
'cache_ts': 1408124980,
'token': u'0IVduczdGR5PkrMqNhBvzW',
'user_id': 5690665774088192L,
'remember': 1,
'token_ts': 1408124980
}
As you can see the token has been changed, and the timestamps updated.
Nearly simutaneously, another request is made that contains the same initial session data.
{
'cache_ts': 1408106895,
'token': u'GXpsaVQh5ZWtqxJMUBpGTr',
'user_id': 5690665774088192L,
'remember': 1,
'token_ts': 1408034938
}
However, that token is now invalid, so the session data is set to None. This wipes the users session, and causes lots of problems. Is there some setting I should be using to extend the life of the UserToken? Is there a more appropriate method than get_user_by_session()? I woud imagine that nearly simultaneous requests with the same session data shouldn't cause enormous issues. The ideal situation would be that if auth received invalid or expired tokens it would just ignore them, and throw an error.
Update 1
Hoped it was something simple like passing False to get_user_by_session(). That of course killed the session immediately.
Update 2
I've found that I only really need the user_id field, and that comes for free with the cookie data. Implementing that reduces the frequency of the issue. However the problem isn't actually fixed, and I'd love some input from anyone with familiarity of this library.
This is due to token_new_age parameter which defaults to 1 day so... every 24h the token will change.
This is a security measure because if someone hacks that session it will only work for 24h.
Parameter 'token_max_age' will also delete the token when time is consumed.
Related
I am builing a member system with a lot of function like memo or post system...etc, so I think it's more safe to use JWT token, so I let my api return jwt token every time I sign in like below
{
"status": 200,
"message": "",
"data": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MGViYzI0MDRhNmVkNDU2NzUwOTk4YjEiLCJ1c2VybmFtZSI6ImpvaG4iLCJleHAiOjE2MjY5NTgwMzEuMjA3LCJpYXQiOjE2MjYzNTMyMzF9.3t_YzKPq4jk6UuIkzTgFaLoXD0Pq5ktmRFp7xg6dFYU"
}
And it contains userID and userName , but here's the problem , every time I have to use something else like userProfilePicture ,userFriend...etc , I have to make an API request, it's really meaningless to do
eventually I manage it like I used axio.interceptor to verify and before I assign my data to context state I fetch user's all data using this token and assign the data to state , Is'nt it the same way to just return all user's data without JWT?.
It seems to me that JWT Token is kind of useless, can anyone tell me that what's the real ,effiecent way to use JWT Token and what's the common managment?
Use can save your token JWT in localstorage... and call it in header of request (or fetch) when you call api...
But dont forget to set expired token of JWT to one week (or one month, or one year... its up to you)...
Or you can set configuration if your JWT, if your token is expired, it will still send the response to your app....
I am thinking should I audit user queries in HttpRequestInterceptor or DiagnosticEventListener for Hot Chocolate v11. The problem with latter is that if the audit failed to write to disk/db, the user will "get away" with the query.
Ideally if audit fail, no operation should proceed. Therefore in theory I should use HttpRequestInterceptor.
But How do I get IRequestContext from IRequestExecutor or IQueryRequestBuilder. I tried googling but documentation is limited.
Neither :)
The HttpRequestInterceptor is meant for enriching the GraphQL request with context data.
The DiagnosticEventListener, on the other hand, is meant for logging or other instrumentations.
If you want to write an audit log, you should instead go for a request middleware. A request middleware can be added like the following.
services
.AddGraphQLServer()
.AddQueryType<Query>()
.UseRequest(next => async context =>
{
})
.UseDefaultPipeline();
The tricky part here is to inspect the request at the right time. Instead of appending to the default pipeline, you can define your own pipeline like the following.
services
.AddGraphQLServer()
.AddQueryType<Query>()
.UseInstrumentations()
.UseExceptions()
.UseTimeout()
.UseDocumentCache()
.UseDocumentParser()
.UseDocumentValidation()
.UseRequest(next => async context =>
{
// write your audit log here and invoke next if the user is allowed to execute
if(isNotAllowed)
{
// if the user is not allowed to proceed create an error result.
context.Result = QueryResultBuilder.CreateError(
ErrorBuilder.New()
.SetMessage("Something is broken")
.SetCode("Some Error Code")
.Build())
}
else
{
await next(context);
}
})
.UseOperationCache()
.UseOperationResolver()
.UseOperationVariableCoercion()
.UseOperationExecution();
The pipeline is basically the default pipeline but adds your middleware right after the document validation. At this point, your GraphQL request is parsed and validated. This means that we know it is a valid GraphQL request that can be processed at this point. This also means that we can use the context.Document property that contains the parsed GraphQL request.
In order to serialize the document to a formatted string use context.Document.ToString(indented: true).
The good thing is that in the middleware, we are in an async context, meaning you can easily access a database and so on. In contrast to that, the DiagnosticEvents are sync and not meant to have a heavy workload.
The middleware can also be wrapped into a class instead of a delegate.
If you need more help, join us on slack.
Click on community support to join the slack channel:
https://github.com/ChilliCream/hotchocolate/issues/new/choose
We're moving and updating our database because it's due for it, but we have an issue concerning authentication. We'd like to connect to the database only with an authentication key.
Our old CouchDB were not using any user and all the databases were public (no users permissions or anything like it). It was working but it is not what we want.
Now, with our 'new' CouchDB, we'd like to have our connections made with an authentication key only, but it looks like there's an expiration on the sessions made and we can't find the way to have a token permanent.
For the context, I'm using couchdb-python for my tools and I found some ways to start a session and get the cookies, therefore the authentication key, but either it is via couchdb-python or the web platform (Fauxton I think it's called), the expiration time is still there and after the timeout (as shown below) the session does expire.
Below is our local.ini for it.
We tried to add both required_valid_user = false and allow_persistent_cookies = true but to no avail.
[couchdb]
uuid = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[couch_peruser]
[chttpd]
port = 5984
bind_address = 192.168.140.66
require_valid_user = false
[httpd]
[couch_httpd_auth]
require_valid_user = false
secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
allow_persistent_cookies = true
timeout = 600
[ssl]
[vhosts]
[admins]
admin = -xxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,xx
I'm pretty sure there's something we're overlooking or that we did not understand correctly.
Is there a way to get an authentication key to be permanent?
Is there a way to get an authentication key to be permanent?
The best would just be to use password authentication. The password never changes (unless you change it, of course).
But if you insist on using a token, you can increase the session timeout to some insane value:
[couch_httpd_auth]
timeout = 99999999999999
This is untested. I don't know what the maximum value is.
Using the Watson Assistant V2 API it is necessary to create a session handle first (create_session(assistantid)) which returns the session ID to use in the individual call to message(assistantid,sessionid,request). The session maintains the conversation state and therefore is the equivalent to the context id parameter of the V1 API.
Unfortunately it seems that there's a 5 minute session timeout by default. The response includes the following header attribute:
{...,"x-watson-session-timeout": [
"x-watson-session-timeout",
"session_timeout=300"
],...}
Any attempt to change this parameter by using the set_default_headers() method of the assistant object or by adding the optional header parameter to the create_session() call seems to have no effect. As I have not found any documentation of how to update this parameter correctly I just tried several alternatives:
1) self.assistant.set_default_headers({'x-watson-session-timeout':"['x-watson-session-timeout','session_timeout=3600']"})
2) self.assistant.set_default_headers({'x-watson-session-timeout':"'x-watson-session-timeout','session_timeout=3600'"})
3)self.assistant.set_default_headers({'x-watson-session-timeout':"session_timeout=3600"})
4)self.assistant.set_default_headers({'x-watson-session-timeout':"3600"})
5)self.assistant.set_default_headers({'session_timeout':"3600"})
Nothing is effective. The value of the parameter in the header of the response is still 300.
Do I use incorrect dict pairs to update the parameter? Is there another way to maintain the conversation state longer than 5 minutes using the V2 API? Is it not possible to change it at all?
The value of the session timeout is not under the control of the caller, and is in fact related to the Assistant plan you are using. For the free and standard the timeout is indeed 5 minutes. For the other plans the timeout is larger.
See Retaining information across dialog turns
The current session lasts for as long a user interacts with the assistant, and then up to 60 minutes of inactivity for Plus or Premium plans (5 minutes for Lite or Standard plans).
You can call watson assistant for an other session and resend your message. Keep your context...
Or just increase timeout limit in assistant setting on IBM Cloud with the right plan.
function createSession(end) {
assistant.createSession({
assistantId: watsonID }).then(res => {
sessionId=res.result.session_id;
if(end){
console.log("\x1b[32m%s\x1b[0m","new session "+sessionId);
}else{
console.log("session id :"+ sessionId);
console.log("http://"+host+":"+port);
}
});
}
createSession();
function callWatsonClient(payload,res) {
assistant.message(payload,function(err, data) {
if(data == null){
createSession(true);
//this not keep the context
var data ={result:{context:"",output:{generic:[{text:"session expirée, renvoyez le message"}]}}};
res.send(data);
}else{
//normal job
console.log("\x1b[33m%s\x1b[0m" ,JSON.stringify(data.result.output));
}
I have a setup with redux-oidc authenticating against an identity server.
I can log in, and I can see that silenRenew works as expected when the token expires.
There is one problem though.
If I open my site and let the computer go to sleep, when I get back after the expiration period, silent renew has failed with this error:
Frame window timed out
It does not try again once i wake up the computer. Not even when I reload the page.
Is this the expected behavior?
If so, what is the correct way of handling this so the site is not left dead?
If not, does anyone have any idea what I might be doing wrong?
I had faced similar issue , so i did a work-around which looks ugly but still works fine for me, look for comments in the code
this.userManager = new Oidc.UserManager(oidcSettings);
this.userManager.events.addAccessTokenExpiring(() =>
{
this.userManager.signinSilent({scope: oidcSettings.scope, response_type: oidcSettings.response_type})
.then((user: Oidc.User) =>
{
this.handleUser(user);
})
.catch((error: Error) =>
{
// Currently as a dirty work around (looks like problem with gluu server. Need to test with other IDP's as well)
// in order to get the new issued token I just calling getUser() straight after signinSilent().then() promise failing with frame time out
// https://github.com/IdentityModel/oidc-client-js/issues/362
this.userManager.getUser()
.then((user: Oidc.User) =>
{
this.handleUser(user);
});
});
});
Take a look at the logs. It usually tells you what's wrong. On all the situations I faced this error it was due I missed redirect uris on the server. Everything you setup on the client needs to be reflected on the server, otherwise, any callback (callback.html, popup.html, and silent.html for instance from the IS examples), session renewal will fail.