How to Extend Firebase Session Cookies Beyond 2 Weeks - firebase

I'm using Firebase Auth to have users authenticate using their Google Account. I found the token returned by firebase.auth().currentUser.getIdToken is only valid for 1 hour. To allow the session to last longer I tried creating a session cookie as outlined in Manage Session Cookies:
const expiresIn = 60 * 60 * 24 * 5 * 1000;
admin.auth().createSessionCookie(idToken, {expiresIn}).then((sessionCookie) => {
const options = {maxAge: expiresIn, httpOnly: true, secure: true};
res.cookie('session', sessionCookie, options);
res.end(JSON.stringify({status: 'success'});
}
This code successfully created a session cookie and subsequent requests could be verified using admin.auth().verifySessionCookie. All was well until I tried increasing the expiresIn duration. It turns out that Firebase session cookies have a maximum expiration time of 2 weeks. From the docs:
Ability to create session cookies with custom expiration times ranging from 5 minutes to 2 weeks.
For this project I would prefer to have a user log in once and stay logged in. I tried extending the session on every interaction with the server but I didn't find any official documentation on how to do that. It seemed to make sense to call admin.auth().createSessionCookie on the server using the token returned by admin.auth().verifySessionCookie, but that failed with this error:
Failed to extend session: { Error: An internal error has occurred. Raw server response: "{"error":{"code":400,"message":"Invalid value at 'valid_duration' (TYPE_INT64), 604.8","errors":[{"message":"Invalid value at 'valid_duration' (TYPE_INT64), 604.8","domain":"global","reason":"badRequest"}],"status":"INVALID_ARGUMENT"}}"`enter code here`
at FirebaseAuthError.Error (native)
at FirebaseAuthError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:39:28)
at FirebaseAuthError.PrefixedFirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:85:28)
at new FirebaseAuthError (/user_code/node_modules/firebase-admin/lib/utils/error.js:143:16)
at Function.FirebaseAuthError.fromServerError (/user_code/node_modules/firebase-admin/lib/utils/error.js:173:16)
at /user_code/node_modules/firebase-admin/lib/auth/auth-api-request.js:726:49
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
errorInfo:
{ code: 'auth/internal-error',
message: 'An internal error has occurred. Raw server response: "{"error":{"code":400,"message":"Invalid value at \'valid_duration\' (TYPE_INT64), 604.8","errors":[{"message":"Invalid value at \'valid_duration\' (TYPE_INT64), 604.8","domain":"global","reason":"badRequest"}],"status":"INVALID_ARGUMENT"}}"' },
codePrefix: 'auth' }
Is it possible to extend Firebase sessions on the server side without requiring the client to do any work? Is it possible to use Firebase auth with tokens with a longer lifespan than 2 weeks? If not, in there a standard approach on how to achieve incredibly long lived sessions?

Extending it too long can be risky, as if the cookie is leaked, the window of attack will be quite wide. I don't recommend extending the session longer but if this is a requirement, you could try to do the following:
after verifying the session cookie on your server for the user and noticing it is about to expire.
mint a custom token for that user ID with Admin SDK
signInWithCustomToken with that custom token.
user.getIdToken() to get new ID token.
Exchange that ID token for a new session cookie.
The downside is that the claims in the session cookie will correspond to a custom token user.
Notice for client side sessions, the ID token passed around has one hour duration, even though the session is indefinite. This is because a refresh token lives on the device and is used to exchange new ID tokens. At any time, only the ID token is transmitted limiting the window of attack to one hour if that token is leaked.
I think it would be useful for Firebase Auth to offer an active duration functionality. That would be better for extending sessions continuously in short increments. This would be better than minting an indefinite or very long cookie. An active user would constantly have their session extended. This is not offered by Firebase Auth but you can file a feature request for it.

Related

Handle the revoked or expired Evernote app

One year ago I activated the Evernote API key for an app (for my client). One week ago the key expired. My client mistakenly revoked the app instead of authorizing it for one year more.
I restored the app authorization with the oAuth method:
var oAuth = new EvernoteOAuthNet.EvernoteOAuth(EvernoteOAuthNet.EvernoteOAuth.HostService.Production, "palmaross", "42dd922cb547c0b7", true);
var errorResponse = oAuth.Authorize();
if (!String.IsNullOrEmpty(errorResponse))
{
ENSessionAdvanced.SetSharedSessionDeveloperToken(oAuth.Token, oAuth.NoteStoreUrl);
}
Client successfully authorized the app for one year more:
Now the ENSessionAdvanced.SharedSession.IsAuthenticated = true. OK.
ENNoteStoreClient SC = ENSessionAdvanced.SharedSession.PrimaryNoteStore is OK.
But the SC.GetSyncState() now raises an exception of type EDAMUserException with AUTH_EXPIRED parameter. (Despite the fact the app was successfully authorized for one year more - see above).
For this reason few days ago i requested a new API key for this app,
With this key I have successfully connected my app with Evernote for one year.
But...
With the new API key (= new app?) the SC.GetSyncState() also raises the same exception - AUTH_EXPIRED!!
What can I do to solve the problem?

Newly generated access token in not working instantly in the linkedin-ads API

I'm getting this response (with 401 error code) after using the new refreshed access token:
{'serviceErrorCode': 65601, 'code': 'REVOKED_ACCESS_TOKEN', 'message': 'The token used in the request has been revoked by the user'}
I followed this guide to refresh the access token:
https://learn.microsoft.com/en-us/linkedin/shared/authentication/programmatic-refresh-tokens?view=li-lms-2022-07#step-2-exchanging-a-refresh-token-for-a-new-access-token
Although it works after several seconds. It seems like the issue is from the LinkedIn-Ads API side. Is there an exact time to wait after generating the access token?

How to limit only issue fungible token once with a specific account by Corda Token SDK

Corda Token SDK https://github.com/corda/token-sdk.
By default, the fungible token can be issued many times, to many accounts.
I do not know to limit that fungible token is issued once and sent to a specific account
(after that token will not be issued any more)
Does anyone have an idea?
To implement that, you'd have to do the following:
Create your own EvolvableTokenType.
Your evolvable token type will have 2 custom attributes (that can be changed over time, thus why we chose evolvable over fixed token type):
issued of type boolean
issueAccount of type AbstractParty
Create a contract that validates your evolvable token type (it should extend EvolvableTokenContract):
Implement additionalCreateChecks: You can keep it empty.
Implement additionalUpdateChecks: Here you can validate that you can only update the value of issued to true, you cannot update it to false (this will allow issuing more of your token type which we don't want).
Create a flow that creates your evolvable token type, it sets the issueAccount to the value that you pass as input parameter and sets issued to false.
Now you can create your evolvable token token type and use it to issue tokens of that type.
Create a flow that issues tokens of your token type:
It will fetch the latest version of your evolvable token type.
If the value of issued is true, throw a FlowException that this token has already been issued and you cannot issue it again.
Use the returned state to get the issueAccount value.
Call the IssueToken flow to issue your token type to issueAccount. Of course you need to generate a new key for the account using RequestKeyForAccount and wrap the returned PublicKey in an instance of AnonymousParty.
Now the most important part (your requirement): Call UpdateEvolvableToken flow to update your evolvable token type and set issued to true. This way if someone calls your issue tokens flow again, it will throw an exception because your token type has been issued.
The Kotlin template (token branch) has a high level example of EvolvableTokenType:
Type: https://github.com/corda/cordapp-template-kotlin/blob/token-template/contracts/src/main/kotlin/com/template/states/ExampleEvolvableTokenType.kt
Contract: https://github.com/corda/cordapp-template-kotlin/blob/token-template/contracts/src/main/kotlin/com/template/ExampleEvolvableTokenTypeContract.kt
Flow (it has 2 flows, create token type and issue it): https://github.com/corda/cordapp-template-kotlin/blob/token-template/workflows/src/main/kotlin/com/template/flows/ExampleFlowWithEvolvableToken.kt
Also the Tokens SDK has an example that uses EvolvableTokenType where the House token has an attribute that can change (valuation):
https://github.com/corda/token-sdk/blob/master/docs/DvPTutorial.md#define-your-states-and-contracts

Meteor.user() on iron-router server side

How can check, on server side route, if user is logged?
I would add check on 'before', but Metor.user() don't work here.
thanks in advance.
p.s. I have found How to get Meteor.user() to return on the server side?, but not work on iron-router
I'm afraid that this is not possible. I guess that the problem comes from the fact that you're trying to connect to the server with two different protocols - both literally and in logically - so there is no obvious way to relate this two actions.
There is, however, a pretty simple solution that may suit your needs. You'll need to develop a simple system of privileges tokens, or secret keys, or whatever you call them. First, create a server method
var Secrets = new Meteor.Collection("secrets"); // only on server!!!
Meteor.methods({
getSecretKey: function () {
if (!this.userId)
// check if the user has privileges
throw Meteor.Error(403);
return Secrets.insert({_id: Random.id(), user: this.userId});
},
});
Then, you can now use it on the client to get the secretKey which attach to your AJAX request (or something), either within the HTTP header or in the URL itself. Fear not!
They will all be encrypted if you're using HTTPS.
On the server side you can now retrieve the secretKey from the incoming request and check if it is present in the Secrets collection. You'll know then if the user is granted certain privileges or not.
Also you may want to remove your secret keys from the collection after some time for safety reasons.
If what you're looking to do is to authenticate the Meteor.user making the request, I'm currently doing this within the context of IronRouter.route(). The request must be made with a valid user ID and auth token in the header. I call this function from within Router.route(), which then gives me access to this.user:
###
Verify the request is being made by an actively logged in user
#context: IronRouter.Router.route()
###
authenticate = ->
# Get the auth info from header
userId = this.request.headers['x-user-id']
loginToken = this.request.headers['x-auth-token']
# Get the user from the database
if userId and loginToken
user = Meteor.users.findOne {'_id': userId, 'services.resume.loginTokens.token': loginToken}
# Return an error if the login token does not match any belonging to the user
if not user
respond.call this, {success: false, message: "You must be logged in to do this."}, 401
# Attach the user to the context so they can be accessed at this.user within route
this.user = user
###
Respond to an HTTP request
#context: IronRouter.Router.route()
###
respond = (body, statusCode=200, headers={'Content-Type':'text/json'}) ->
this.response.writeHead statusCode, headers
this.response.write(JSON.stringify(body))
this.response.end()
This code was heavily inspired by RestStop and RestStop2. It's part of a meteor package for writing REST APIs in Meteor 0.9.0+ (built on top of Iron Router). You can check out the complete source code here:
https://github.com/krose72205/meteor-restivus

How to increase Azure ACS login timeout

The Azure Training Kit includes a lab titled "IntroToACS2". In it, you create a WebRole and enable ACS so that you can login using your Google, Live, or Yahoo id. After logging in, if I wait 10 minutes or so and then refresh the page, I'm redirected back to the login page.
How can I increase the Azure ACS login timeout?
Here's what I found:
http://msdn.microsoft.com/en-us/library/gg185906.aspx#BKMK_5
Token Lifetime
The Token lifetime property allows you to specify the amount of time for a security token issued by ACS to the relying party application to remain valid. By default, in ACS, this value is set to 10 minutes (600 seconds). In ACS, this value must be greater than zero but less than or equal to 24 hours (86400 seconds).
While the maximum lifetime is 24 hours it's possible to automatically renew the ACS token by adding the following 6 lines of code in ShowSigninPage function, just before the existing loop over identityProviders:
for (var i in identityProviders) {
if (cookieName !== null && cookieName == identityProviders[i].Name) {
window.location = identityProviders[i].LoginUrl;
return null;
} }
// Loop through the identity providers for (var i in identityProviders) {
...
For more info the automatic renewal approach see: http://social.msdn.microsoft.com/Forums/en-US/windowsazuresecurity/thread/0430c4aa-ab10-4a72-b115-91b2600bfcd0
I think what you really want is to increase your application's session lifetime, and not the ACS issued token lifetime.
How do I increase session timeout with W.I.F / SAML tokens / FedAuth cookie

Resources