Advise on generating a new session identifier after successful authentication

ISSUE DESCRIPTION:

Currently we use OpenID Connect for user authentication. When a user initially navigates to the application, an ss-id (session identifier) is set. The user is then redirected for authentication. Upon successful authentication, the user is redirected back to the application where the same ss-id is used for the authenticated session.

The reuse of the same ss-id before and after authentication allows for potential session fixation attacks.

Can you please suggest the best way to generate a new, unique session identifier to replace the initial ss-id, Upon successful authentication?
If authentication is successful, what is the best way to create a new session identifier and store it?

Please provide your Auth configuration including where the session is stored and URLs that’s used to Authenticate.

we are making use of AuthenticateAsync() as below. We are calling the below functions

public abstract override Task<object> **AuthenticateAsync**(IServiceBase authService, IAuthSession session, Authenticate request, CancellationToken token=default);

and then calling Init() which Sets the CallbackUrl and session.ReferrerUrl if not set and initializes the session tokens for the AuthProvider

protected IAuthTokens **Init**(IServiceBase authService, ref IAuthSession session, Authenticate request) 

and then we make a call to GetAbsoluteUrl() to get the redirect url

public static string **GetAbsoluteUrl**(this IRequest httpReq, string url) 

and we make a call to AddAuthToken() to add AccessToken, RefreshToken, RequestToken to the session
session.AddAuthToken(tokens)

and then we are calling SaveSessionAsync()

public static async Task **SaveSessionAsync**(this IAuthProvider provider, IServiceBase authService, IAuthSession session, TimeSpan? sessionExpiry = null, CancellationToken token=default)

public virtual async Task<IHttpResult> **OnAuthenticatedAsync**(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo, CancellationToken token=default)

protected virtual AuthContext **CreateAuthContext**(IServiceBase authService=null, IAuthSession session=null, IAuthTokens tokens=null)

override method from ServiceStack AuthenticateAsync will take care of the authentication process, we are expecting to change the session token after successful login. If I use

authService.Request.GenerateNewSessionCookiesAsync(session);
before calling OnAuthenticatedAsync() it is working.

Is this the correct way to handle this? Could you please suggest us the best way to handle this?

Yes that’s what should be called, it would normally get called for most Auth Providers at:

Except some OAuth Providers requires additional information stored in the session to correlate the callback so it’s not called then. So if you call Request.GenerateNewSessionCookiesAsync() at the start before authenticating it should generate new session cookies for that request.

Thank you for your suggestion. Could you please confirm
authFeature?.HasSessionFeature was introduced in which ServiceStack version?

Looks like it was added in this commit on January 2, 2024 so it’s in v8.1.

1 Like

Can you please suggest the best approach to handle this in ServiceStack version 6.9 since HasSessionFeature is not available in ServiceStack version 6.9

I am trying with the below code and only before authetication generateNewCookies is true. But in order to generate new session id after successful authentication generateNewCookies value is false.
The public override Task AuthenticateAsync() is called 2 times i.e on hitting the url before authentication and it is called again after successful authentication,
before authentication generateNewCookies value is true but after authentication generateNewCookies value is false. So how can we handle this to generate new session id after successful authentication?

var authFeature = HostContext.GetPlugin<AuthFeature>();
var generateNewCookies = authFeature.GenerateNewSessionCookiesOnAuthentication
  && string.IsNullOrEmpty(Request.QueryString["oauth_token"])
  && string.IsNullOrEmpty(Request.QueryString["State"])
  && string.IsNullOrEmpty(Request.QueryString["state"]);

if (generateNewCookies)
{
    Request.GenerateNewSessionCookiesAsync(session, token).ConfigAwait();
}

HasSessionFeature is just a check if the SessionFeature plugin is registered (e.g. HostContext.HasPlugin<SessionFeature>()), you don’t need to check for it in your code as your App is always using it.

I don’t see how authFeature.GenerateNewSessionCookiesOnAuthentication can be false, it’s a singleton that’s initialized on Startup, nothing should be changing it after it’s initialized.

I’d recommend upgrading to the latest version, otherwise you could execute custom logic with a Global Request Filter, e.g:

RegisterTypedRequestFilterAsync<Authenticate>(async (req, res, dto) =>
{
    // implement custom check for when cookies should be regenerated 
    if (MyShouldRegenerateCookies(req)) 
    {
        var session = await req.GetSessionAsync();
        await req.GenerateNewSessionCookiesAsync(session);
    }
}); 
1 Like