Skip to content

Commit 818b10c

Browse files
committed
Fix SessionId Cookie MaxAge on Hybrid Auth Mode
1 parent 7191fc5 commit 818b10c

File tree

3 files changed

+48
-44
lines changed

3 files changed

+48
-44
lines changed
Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
using CodeBeam.UltimateAuth.Server.Auth;
1+
using CodeBeam.UltimateAuth.Core;
2+
using CodeBeam.UltimateAuth.Core.Domain;
3+
using CodeBeam.UltimateAuth.Server.Auth;
24
using CodeBeam.UltimateAuth.Server.Options;
35
using Microsoft.AspNetCore.Http;
46

57
namespace CodeBeam.UltimateAuth.Server.Cookies;
68

79
internal sealed class DefaultUAuthCookiePolicyBuilder : IUAuthCookiePolicyBuilder
810
{
9-
public CookieOptions Build(CredentialResponseOptions response, AuthFlowContext context, TimeSpan? logicalLifetime)
11+
public CookieOptions Build(CredentialResponseOptions response, AuthFlowContext context, CredentialKind kind)
1012
{
1113
if (response.Cookie is null)
1214
throw new InvalidOperationException("Cookie policy requested but Cookie options are null.");
@@ -18,11 +20,11 @@ public CookieOptions Build(CredentialResponseOptions response, AuthFlowContext c
1820
HttpOnly = src.HttpOnly,
1921
Secure = src.SecurePolicy == CookieSecurePolicy.Always,
2022
Path = src.Path,
21-
Domain = src.Domain
23+
Domain = src.Domain,
24+
SameSite = ResolveSameSite(src, context)
2225
};
2326

24-
options.SameSite = ResolveSameSite(src, context);
25-
ApplyLifetime(options, src, logicalLifetime);
27+
ApplyLifetime(options, src, context, kind);
2628

2729
return options;
2830
}
@@ -41,30 +43,51 @@ private static SameSiteMode ResolveSameSite(UAuthCookieOptions cookie, AuthFlowC
4143
};
4244
}
4345

44-
private static void ApplyLifetime(CookieOptions target, UAuthCookieOptions src, TimeSpan? logicalLifetime)
46+
private static void ApplyLifetime(CookieOptions target, UAuthCookieOptions src, AuthFlowContext context, CredentialKind kind)
4547
{
4648
var buffer = src.Lifetime.IdleBuffer ?? TimeSpan.Zero;
47-
TimeSpan? baseLifetime = null;
49+
var baseLifetime = ResolveBaseLifetime(context, kind, src);
4850

49-
// 1️⃣ Hard MaxAge override (base)
50-
if (src.MaxAge is not null)
51-
{
52-
baseLifetime = src.MaxAge;
53-
}
54-
// 2️⃣ Absolute lifetime override (base)
55-
else if (src.Lifetime.AbsoluteLifetimeOverride is not null)
51+
if (baseLifetime is not null)
5652
{
57-
baseLifetime = src.Lifetime.AbsoluteLifetimeOverride;
53+
target.MaxAge = baseLifetime.Value + buffer;
5854
}
59-
// 3️⃣ Logical lifetime (effective)
60-
else if (logicalLifetime is not null)
55+
}
56+
57+
private static TimeSpan? ResolveBaseLifetime(AuthFlowContext context, CredentialKind kind, UAuthCookieOptions src)
58+
{
59+
if (src.MaxAge is not null)
60+
return src.MaxAge;
61+
62+
if (src.Lifetime.AbsoluteLifetimeOverride is not null)
63+
return src.Lifetime.AbsoluteLifetimeOverride;
64+
65+
return kind switch
6166
{
62-
baseLifetime = logicalLifetime;
63-
}
67+
CredentialKind.Session => ResolveSessionLifetime(context),
68+
CredentialKind.RefreshToken => context.EffectiveOptions.Options.Tokens.RefreshTokenLifetime,
69+
CredentialKind.AccessToken => context.EffectiveOptions.Options.Tokens.AccessTokenLifetime,
70+
_ => null
71+
};
72+
}
6473

65-
if (baseLifetime is not null)
74+
private static TimeSpan? ResolveSessionLifetime(AuthFlowContext context)
75+
{
76+
var sessionIdle = context.EffectiveOptions.Options.Session.IdleTimeout;
77+
var refresh = context.EffectiveOptions.Options.Tokens.RefreshTokenLifetime;
78+
79+
return context.EffectiveMode switch
6680
{
67-
target.MaxAge = baseLifetime.Value + buffer;
68-
}
81+
UAuthMode.PureOpaque => sessionIdle,
82+
UAuthMode.Hybrid => Max(sessionIdle, refresh),
83+
_ => sessionIdle
84+
};
85+
}
86+
87+
private static TimeSpan? Max(TimeSpan? a, TimeSpan? b)
88+
{
89+
if (a is null) return b;
90+
if (b is null) return a;
91+
return a > b ? a : b;
6992
}
7093
}

src/CodeBeam.UltimateAuth.Server/Cookies/IUAuthCookiePolicyBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
using CodeBeam.UltimateAuth.Server.Auth;
33
using CodeBeam.UltimateAuth.Server.Options;
44
using CodeBeam.UltimateAuth.Core.Contracts;
5+
using CodeBeam.UltimateAuth.Core.Domain;
56

67
namespace CodeBeam.UltimateAuth.Server.Cookies;
78

89
public interface IUAuthCookiePolicyBuilder
910
{
10-
CookieOptions Build(CredentialResponseOptions response, AuthFlowContext context, TimeSpan? logicalLifetime);
11+
CookieOptions Build(CredentialResponseOptions response, AuthFlowContext context, CredentialKind kind);
1112
}

src/CodeBeam.UltimateAuth.Server/Infrastructure/DefaultCredentialResponseWriter.cs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,7 @@ private void WriteCookie(HttpContext context, CredentialKind kind, string value,
5858
if (options.Cookie is null)
5959
throw new InvalidOperationException($"Cookie options missing for credential '{kind}'.");
6060

61-
var logicalLifetime = ResolveLogicalLifetime(auth, kind);
62-
var cookieOptions = _cookiePolicy.Build(options, auth, logicalLifetime);
63-
61+
var cookieOptions = _cookiePolicy.Build(options, auth, kind);
6462
_cookieManager.Write(context, options.Cookie.Name, value, cookieOptions);
6563
}
6664

@@ -80,22 +78,4 @@ private static CredentialResponseOptions ResolveDelivery(EffectiveAuthResponse r
8078
CredentialKind.RefreshToken => response.RefreshTokenDelivery,
8179
_ => throw new ArgumentOutOfRangeException(nameof(kind))
8280
};
83-
84-
private static TimeSpan? ResolveLogicalLifetime(AuthFlowContext auth, CredentialKind kind)
85-
{
86-
// TODO: Move this method to policy on implementing
87-
return kind switch
88-
{
89-
CredentialKind.Session
90-
=> auth.EffectiveOptions.Options.Session.IdleTimeout + auth.OriginalOptions.Cookie.Session.Lifetime.IdleBuffer,
91-
92-
CredentialKind.RefreshToken
93-
=> auth.EffectiveOptions.Options.Tokens.RefreshTokenLifetime + auth.OriginalOptions.Cookie.RefreshToken.Lifetime.IdleBuffer,
94-
95-
CredentialKind.AccessToken
96-
=> auth.EffectiveOptions.Options.Tokens.AccessTokenLifetime + auth.OriginalOptions.Cookie.AccessToken.Lifetime.IdleBuffer,
97-
98-
_ => null
99-
};
100-
}
10181
}

0 commit comments

Comments
 (0)