Advertisement
Ravaut123

Middleware.JwtAuthentication

May 19th, 2016
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 7.37 KB | None | 0 0
  1. { *************************************************************************** }
  2. { }
  3. { Delphi MVC Framework }
  4. { }
  5. { Copyright (c) 2010-2015 Daniele Teti and the DMVCFramework Team }
  6. { }
  7. { https://github.com/danieleteti/delphimvcframework }
  8. { }
  9. { *************************************************************************** }
  10. { }
  11. { Licensed under the Apache License, Version 2.0 (the "License"); }
  12. { you may not use this file except in compliance with the License. }
  13. { You may obtain a copy of the License at }
  14. { }
  15. { http://www.apache.org/licenses/LICENSE-2.0 }
  16. { }
  17. { Unless required by applicable law or agreed to in writing, software }
  18. { distributed under the License is distributed on an "AS IS" BASIS, }
  19. { WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
  20. { See the License for the specific language governing permissions and }
  21. { limitations under the License. }
  22. { }
  23. { *************************************************************************** }
  24.  
  25. unit Middleware.JwtAuthentication;
  26.  
  27. interface
  28.  
  29. uses
  30.   MVCFramework,
  31.   MVCFramework.Commons,
  32.   MVCFramework.Logger,
  33.   MVCFramework.JWT,
  34.   System.Generics.Collections,
  35.   System.DateUtils;
  36.  
  37. type
  38.   TMVCJwtAuthenticationMiddleware = class(TInterfacedObject, IMVCMiddleware)
  39.   strict private
  40.     FMVCAuthenticationHandler: IMVCAuthenticationHandler;
  41.  
  42.     procedure Render(const AErrorCode: UInt16; const AErrorMessage: string; Context: TWebContext;
  43.       const AErrorClassName: string = ''); overload;
  44.  
  45.   protected
  46.     FSecret: string;
  47.     procedure OnBeforeRouting(Context: TWebContext; var Handled: Boolean);
  48.     procedure OnAfterControllerAction(Context: TWebContext;
  49.       const AActionName: string; const Handled: Boolean);
  50.     procedure OnBeforeControllerAction(Context: TWebContext;
  51.       const AControllerQualifiedClassName: string; const AActionName: string;
  52.       var Handled: Boolean);
  53.   public
  54.     constructor Create(AMVCAuthenticationHandler: IMVCAuthenticationHandler;
  55.       ASecret: string = 'DelphiMVCFramework'); virtual;
  56.   end;
  57.  
  58. implementation
  59.  
  60. uses
  61.   System.SysUtils, MVCFramework.Session
  62.   {$IF CompilerVersion < 27}
  63.     , Data.DBXJSON
  64. {$ELSE}
  65.     , System.JSON, Web.ApacheHTTP
  66. {$ENDIF}
  67. {$IF CompilerVersion >= 21}
  68.     , System.NetEncoding
  69. {$ELSE}
  70.     , Soap.EncdDecd
  71. {$ENDIF};
  72.  
  73.  
  74.  
  75. { TMVCSalutationMiddleware }
  76.  
  77. constructor TMVCJwtAuthenticationMiddleware.Create(AMVCAuthenticationHandler
  78.   : IMVCAuthenticationHandler; ASecret: string);
  79. begin
  80.   inherited Create;
  81.   FMVCAuthenticationHandler := AMVCAuthenticationHandler;
  82.   FSecret := ASecret;
  83. end;
  84.  
  85. procedure TMVCJwtAuthenticationMiddleware.OnAfterControllerAction
  86.   (Context: TWebContext; const AActionName: string; const Handled: Boolean);
  87. begin
  88.   // do nothing
  89. end;
  90.  
  91.  
  92. procedure TMVCJwtAuthenticationMiddleware.OnBeforeControllerAction
  93.   (Context: TWebContext; const AControllerQualifiedClassName,
  94.   AActionName: string; var Handled: Boolean);
  95. var
  96.   lAuthRequired: Boolean;
  97.   lIsAuthorized: Boolean;
  98.   lIsValid: Boolean;
  99.   lJWT: TJWT;
  100.   lAuthHeader: string;
  101.   lToken: string;
  102.   lUserName: string;
  103.   lPassWord: string;
  104.   lRoles: TList<string>;
  105.   lSessionData: TSessionData;
  106.   lPair: TPair<String, String>;
  107. begin
  108.   // check if the resource is protected
  109.   FMVCAuthenticationHandler.OnRequest(AControllerQualifiedClassName,
  110.     AActionName, LAuthRequired);
  111.   if not LAuthRequired then
  112.   begin
  113.     Handled := False;
  114.     Exit;
  115.   end;
  116.  
  117.   if SameText(AActionName, 'Login') and (Context.Request.HTTPMethod = httpPOST) then
  118.   begin
  119.     lUserName:= Context.Request.Headers['UserName'];
  120.     lPassWord:=  Context.Request.Headers['PassWord'];
  121.     if (lUserName.IsEmpty) or
  122.        (lPassWord.IsEmpty) then
  123.     begin
  124.       Render(http_status.Unauthorized, 'UserName and PassWord Required', Context);
  125.       Handled := True;
  126.       Exit;
  127.     end;
  128.  
  129.     // check the authorization for the requested resource
  130.     lRoles := TList<string>.Create;
  131.     try
  132.       lSessionData := TSessionData.Create;
  133.       try
  134.         FMVCAuthenticationHandler.OnAuthentication(lUserName, lPassWord,
  135.           lRoles, lIsValid, lSessionData);
  136.         if LIsValid then
  137.         begin
  138.           lJWT := TJWT.Create(FSecret);
  139.           try
  140.             lJWT.Claims.Issuer := 'AraCrav app';
  141.             lJWT.Claims.ExpirationTime := Now + OneHour;
  142.             lJWT.Claims.NotBefore := Now - OneMinute * 5;
  143.             lJWT.CustomClaims['username'] := lUserName;
  144. //          Render(lJWT.GetToken);
  145.             InternalRender(lJWT.GetToken, TMVCConstants.DEFAULT_CONTENT_TYPE, TMVCConstants.DEFAULT_CONTENT_CHARSET, Context);
  146.             Exit;
  147.           finally
  148.             lJWT.Free;
  149.           end;
  150.           Context.LoggedUser.Roles.AddRange(LRoles);
  151.           Context.LoggedUser.UserName := lUserName;
  152.           Context.LoggedUser.LoggedSince := Now;
  153. //          Context.LoggedUser.Realm := FRealm;
  154.           Context.LoggedUser.SaveToSession(Context.Session);
  155.  
  156.           // save sessiondata to the actual session
  157.           for LPair in lSessionData do
  158.           begin
  159.             Context.Session[LPair.Key] := LPair.Value;
  160.           end;
  161.         end;
  162.       finally
  163.         lSessionData.Free;
  164.       end;
  165.     finally
  166.       LRoles.Free;
  167.     end;
  168.   end;
  169.  
  170.   lJWT := TJWT.Create(FSecret);
  171.   try
  172.     lAuthHeader := Context.Request.Headers['Authentication'];
  173.     if lAuthHeader.IsEmpty then
  174.     begin
  175.       Render(http_status.Unauthorized, 'Authentication Required', Context);
  176.       Handled := True;
  177.       Exit;
  178.     end;
  179.  
  180.     if lAuthHeader.StartsWith('bearer', True) then
  181.     begin
  182.       lToken := lAuthHeader.Remove(0, 'bearer'.Length).Trim;
  183.     end;
  184.  
  185.     if not lJWT.IsValidToken(lToken) then
  186.     begin
  187.       Render(http_status.Unauthorized, 'Invalid Token, Authentication Required', Context);
  188.       Handled := True;
  189.     end
  190.     else
  191.     begin
  192.       lJWT.LoadToken(lToken);
  193.       if lJWT.CustomClaims['username'].IsEmpty then
  194.       begin
  195.         Render(http_status.Unauthorized, 'Invalid Token, Authentication Required', Context);
  196.         Handled := True;
  197.       end
  198.       else
  199.       begin
  200.         lIsAuthorized:= False;
  201.         FMVCAuthenticationHandler.OnAuthorization(Context.LoggedUser.Roles,
  202.           AControllerQualifiedClassName, AActionName, lIsAuthorized);
  203.         if lIsAuthorized then
  204.         begin
  205.           Handled := False;
  206.         end
  207.         else
  208.         begin
  209.           Render(http_status.Forbidden, 'Authorization Forbidden', Context);
  210.           Handled := True;
  211.         end;
  212.       end;
  213.     end;
  214.   finally
  215.     lJWT.Free;
  216.   end;
  217.  
  218. end;
  219.  
  220. procedure TMVCJwtAuthenticationMiddleware.OnBeforeRouting
  221.   (Context: TWebContext; var Handled: Boolean);
  222. begin
  223.   // do nothing
  224. end;
  225.  
  226. procedure TMVCJwtAuthenticationMiddleware.Render(const AErrorCode: UInt16; const AErrorMessage: string; Context: TWebContext;
  227.       const AErrorClassName: string);
  228. var
  229.   j: TJSONObject;
  230.   status: string;
  231. begin
  232.   Context.Response.StatusCode := AErrorCode;
  233.   Context.Response.ReasonString := AErrorMessage;
  234.   status := 'error';
  235.   if (AErrorCode div 100) = 2 then
  236.     status := 'ok';
  237.   j := TJSONObject.Create;
  238.   j.AddPair('status', status);
  239.   if AErrorClassName = '' then
  240.     j.AddPair('classname', TJSONNull.Create)
  241.   else
  242.     j.AddPair('classname', AErrorClassName);
  243.   j.AddPair('message', AErrorMessage);
  244.  
  245.   InternalRender(j, TMVCConstants.DEFAULT_CONTENT_TYPE, TMVCConstants.DEFAULT_CONTENT_CHARSET, Context);
  246.  
  247. end;
  248.  
  249. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement