Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 41 additions & 31 deletions src/Horse.JWT.pas
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ TSkipRouteMethod = record

TSkipRouteMethods = TArray<TSkipRouteMethod>;
{$IF DEFINED(FPC)}
TOnResponse = {$IF DEFINED(HORSE_FPC_FUNCTIONREFERENCES)}reference to {$ENDIF}procedure(const AHorseResponse: THorseResponse; const AMessage: string; const AHTTPStatus: THTTPStatus; const APathInfo: string);
TOnResponse = {$IF DEFINED(HORSE_FPC_FUNCTIONREFERENCES)}reference to {$ENDIF}procedure(const AHorseResponse: THorseResponse; const AMessage: string; const AHTTPStatus: THTTPStatus);
TOnResponseWithPath = {$IF DEFINED(HORSE_FPC_FUNCTIONREFERENCES)}reference to {$ENDIF}procedure(const AHorseResponse: THorseResponse; const AMessage: string; const AHTTPStatus: THTTPStatus; const APathInfo: string);
{$ELSE}
TOnResponse = reference to procedure(const AHorseResponse: THorseResponse; const AMessage: string; const AHTTPStatus: THTTPStatus; const APathInfo: string);
TOnResponse = reference to procedure(const AHorseResponse: THorseResponse; const AMessage: string; const AHTTPStatus: THTTPStatus);
TOnResponseWithPath = reference to procedure(const AHorseResponse: THorseResponse; const AMessage: string; const AHTTPStatus: THTTPStatus; const APathInfo: string);
{$ENDIF}

IHorseJWTConfig = interface
Expand Down Expand Up @@ -78,8 +80,10 @@ TSkipRouteMethod = record
function ExpectedAudience(const AValue: TArray<string>): IHorseJWTConfig; overload;
function SessionClass: TClass; overload;
function SessionClass(const AValue: TClass): IHorseJWTConfig; overload;
function OnResponse: TOnResponse; overload;
function OnResponse(const AValue: TOnResponse): IHorseJWTConfig; overload;
function OnResponse: TOnResponse; overload;
function OnResponseWithPath: TOnResponseWithPath;
function OnResponse(const AValue: TOnResponse): IHorseJWTConfig; overload;
function OnResponse(const AValue: TOnResponseWithPath): IHorseJWTConfig; overload;
end;

{ THorseJWTConfig }
Expand All @@ -97,7 +101,8 @@ THorseJWTConfig = class(TInterfacedObject, IHorseJWTConfig)
FIsRequiredNotBefore: Boolean;
FIsRequiredSubject: Boolean;
FSessionClass: TClass;
FOnResponse: TOnResponse;
FOnResponse: TOnResponse;
FOnResponseWithPath: TOnResponseWithPath;
function SkipRoutes: TArray<string>; overload;
function SkipRoutes(const ARoutes: TArray<string>): IHorseJWTConfig; overload;
function SkipRoutes(const ARoute: string): IHorseJWTConfig; overload;
Expand All @@ -121,8 +126,10 @@ THorseJWTConfig = class(TInterfacedObject, IHorseJWTConfig)
function ExpectedAudience(const AValue: TArray<string>): IHorseJWTConfig; overload;
function SessionClass: TClass; overload;
function SessionClass(const AValue: TClass): IHorseJWTConfig; overload;
function OnResponse: TOnResponse; overload;
function OnResponse: TOnResponse; overload;
function OnResponseWithPath: TOnResponseWithPath;
function OnResponse(const AValue: TOnResponse): IHorseJWTConfig; overload;
function OnResponse(const AValue: TOnResponseWithPath): IHorseJWTConfig; overload;
public
constructor Create;
class function New: IHorseJWTConfig;
Expand Down Expand Up @@ -209,6 +216,15 @@ procedure Middleware(AHorseRequest: THorseRequest; AHorseResponse: THorseRespons
Result := (LJWT.Signature = LSignCalc);
end;
{$ENDIF}
procedure DoResponse(const AMessage: string; const AStatus: THTTPStatus);
begin
if Assigned(LConfig.OnResponseWithPath) then
LConfig.OnResponseWithPath()(AHorseResponse, AMessage, AStatus, LPathInfo)
else if Assigned(LConfig.OnResponse) then
LConfig.OnResponse()(AHorseResponse, AMessage, AStatus)
else
AHorseResponse.Send(AMessage).Status(AStatus);
end;
begin
LConfig := AConfig;
if AConfig = nil then
Expand Down Expand Up @@ -249,24 +265,18 @@ procedure Middleware(AHorseRequest: THorseRequest; AHorseResponse: THorseRespons
LToken := AHorseRequest.Headers[LConfig.Header];
if LToken.IsEmpty then
LToken := AHorseRequest.Cookie.Items[LConfig.Header];

if LToken.Trim.IsEmpty and not AHorseRequest.Query.TryGetValue(
LConfig.Header, LToken) and not AHorseRequest.Query.TryGetValue(
LHeaderNormalize, LToken) then
begin
if Assigned(LConfig.OnResponse()) then
LConfig.OnResponse()(AHorseResponse, TOKEN_NOT_FOUND, THTTPStatus.Unauthorized, LPathInfo)
else
AHorseResponse.Send(TOKEN_NOT_FOUND).Status(THTTPStatus.Unauthorized);
DoResponse(TOKEN_NOT_FOUND, THTTPStatus.Unauthorized);
raise EHorseCallbackInterrupted.Create(TOKEN_NOT_FOUND);
end;

if Pos('bearer', LowerCase(LToken)) = 0 then
begin
if Assigned(LConfig.OnResponse()) then
LConfig.OnResponse()(AHorseResponse, INVALID_AUTHORIZATION_TYPE, THTTPStatus.Unauthorized, LPathInfo)
else
AHorseResponse.Send(INVALID_AUTHORIZATION_TYPE).Status(THTTPStatus.Unauthorized);
DoResponse(INVALID_AUTHORIZATION_TYPE, THTTPStatus.Unauthorized);
raise EHorseCallbackInterrupted.Create(INVALID_AUTHORIZATION_TYPE);
end;

Expand All @@ -292,20 +302,14 @@ procedure Middleware(AHorseRequest: THorseRequest; AHorseResponse: THorseRespons
try
LJWT := TJOSEContext.Create(LToken, TJWTClaims);
except
if Assigned(LConfig.OnResponse()) then
LConfig.OnResponse()(AHorseResponse, UNAUTHORIZED, THTTPStatus.Unauthorized, LPathInfo)
else
AHorseResponse.Send(UNAUTHORIZED).Status(THTTPStatus.Unauthorized);
DoResponse(UNAUTHORIZED, THTTPStatus.Unauthorized);
raise EHorseCallbackInterrupted.Create(UNAUTHORIZED);
end;

try
if LJWT.GetJOSEObject = nil then
begin
if Assigned(LConfig.OnResponse()) then
LConfig.OnResponse()(AHorseResponse, UNAUTHORIZED, THTTPStatus.Unauthorized, LPathInfo)
else
AHorseResponse.Send(UNAUTHORIZED).Status(THTTPStatus.Unauthorized);
DoResponse(UNAUTHORIZED, THTTPStatus.Unauthorized);
raise EHorseCallbackInterrupted.Create(UNAUTHORIZED);
end;

Expand Down Expand Up @@ -377,10 +381,7 @@ procedure Middleware(AHorseRequest: THorseRequest; AHorseResponse: THorseRespons
except
on E: Exception do
begin
if Assigned(LConfig.OnResponse()) then
LConfig.OnResponse()(AHorseResponse, UNAUTHORIZED, THTTPStatus.Unauthorized, LPathInfo)
else
AHorseResponse.Send(UNAUTHORIZED).Status(THTTPStatus.Unauthorized);
DoResponse(UNAUTHORIZED, THTTPStatus.Unauthorized);
raise EHorseCallbackInterrupted.Create(UNAUTHORIZED);
end;
end;
Expand All @@ -392,10 +393,7 @@ procedure Middleware(AHorseRequest: THorseRequest; AHorseResponse: THorseRespons
raise;
on E: Exception do
begin
if Assigned(LConfig.OnResponse()) then
LConfig.OnResponse()(AHorseResponse, 'Invalid token authorization. ' + E.Message, THTTPStatus.Unauthorized, LPathInfo)
else
AHorseResponse.Send('Invalid token authorization. ' + E.Message).Status(THTTPStatus.Unauthorized);
DoResponse('Invalid token authorization. ' + E.Message, THTTPStatus.Unauthorized);
raise EHorseCallbackInterrupted.Create;
end;
end;
Expand Down Expand Up @@ -577,6 +575,7 @@ function THorseJWTConfig.SkipRouteMethods(const AValue: TSkipRouteMethods): IHor
I: Integer;
begin
FSkipRouteMethods := AValue;

for I := 0 to High(FSkipRouteMethods) do
begin
if (FSkipRouteMethods[I].Route <> '') and (FSkipRouteMethods[I].Route[1] <> '/') then
Expand Down Expand Up @@ -605,10 +604,21 @@ function THorseJWTConfig.OnResponse: TOnResponse;
Result := FOnResponse;
end;

function THorseJWTConfig.OnResponseWithPath: TOnResponseWithPath;
begin
Result := FOnResponseWithPath;
end;

function THorseJWTConfig.OnResponse(const AValue: TOnResponse): IHorseJWTConfig;
begin
FOnResponse := AValue;
Result := Self;
end;

function THorseJWTConfig.OnResponse(const AValue: TOnResponseWithPath): IHorseJWTConfig;
begin
FOnResponseWithPath := AValue;
Result := Self;
end;

end.