unit Common.Middleware.RejectExpiredJwt;

interface

uses
  System.SysUtils, System.DateUtils,
  Sparkle.HttpServer.Module,
  Sparkle.HttpServer.Context,
  Sparkle.Security,
  XData.Module.Base;

type
  TRejectExpiredJwtMiddleware = class(THttpServerMiddleware, IHttpServerMiddleware)
  private
    procedure UnauthorizedAnswer(Resp: THttpServerResponse; const Msg: string);
  protected
    procedure ProcessRequest(Context: THttpServerContext; Next: THttpServerProc); override;
  end;

implementation

uses
  Sparkle.Utils, System.JSON;

{ TRejectExpiredJwtMiddleware }

procedure TRejectExpiredJwtMiddleware.ProcessRequest(Context: THttpServerContext; Next: THttpServerProc);
var
  Expiration: TDateTime;
begin
  if Context.Request.User = nil then
  begin
    Next(Context);
    Exit;
  end;

  if Not Context.Request.User.Claims.Exists('exp') then
  begin
    Next(Context);
    Exit;
  end;

  Expiration := TTimeZone.Local.ToLocalTime(Context.Request.User.Claims['exp'].AsEpoch);

  if Expiration < Now then
  begin
    UnauthorizedAnswer(Context.Response, 'Expired Token');
    Exit
  end;

  Next(Context);
end;

procedure TRejectExpiredJwtMiddleware.UnauthorizedAnswer(Resp: THttpServerResponse; const Msg: string);
begin
  Resp.StatusCode := 401;
  if Msg <> '' then
  begin
    Resp.ContentType := 'text/plain';
    Resp.Headers.SetValue(Header_AccessControlAllowOrigin, '*');
    Resp.Close(TEncoding.UTF8.GetBytes(Msg));
  end;
end;

end.
