restdelphiauthorizationindydelphi-10.4-sydney

How do I implement "Authorization: Bearer <Token>" in a Delphi REST Server?


I have a working REST server (Sydney) that uses a custom header (AuthToken: 'Token') to authorize users.

When I try to use "Authorization: Bearer 'Token'" as a header in a POST request, I get an exception in my rest server as below. enter image description here

It looks like I have to assign a procedure to a TIdHTTPParseAuthenticationEvent, but I cannot find out where to do that.


Solution

  • When you create a Datasnap REST server project, it creates a default TIdHTTPWebBrokerBridge object for you, which is a TIdCustomHTTPServer descendant. You can assign a handler to its OnParseAuthentication event in code (since it is not a visual component on the Form), eg:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FServer := TIdHTTPWebBrokerBridge.Create(Self);
      FServer.OnParseAuthentication := ParseAuthentication; // <-- here
    end;
    
    procedure TForm1.ParseAuthentication(AContext: TIdContext;
      const AAuthType, AAuthData: String;
      var VUsername, VPassword: String;
      var VHandled: Boolean);
    begin
      if TextIsSame(AAuthType, 'Bearer') then begin
        // process AAuthData and assign VUsername and VPassword as needed...
        VHandled := True;
      end;
    end;
    

    UPDATE: starting in Indy v10.6.3.3, the TIdCustomHTTPServer.DoParseAuthentication() method is now virtual, so you can alternatively derive a new class from TIdHTTPWebBrokerBridge and override it, eg:

    type
      TMyHTTPWebBrokerBridge = class(TIdHTTPWebBrokerBridge)
      protected
        function DoParseAuthentication(ASender: TIdContext;
          const AAuthType, AAuthData: String;
          var VUsername, VPassword: String): Boolean; override;
      end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      //FServer := TIdHTTPWebBrokerBridge.Create(Self);
      FServer := TMyHTTPWebBrokerBridge.Create(Self);
    end;
    
    function TMyHTTPWebBrokerBridge.DoParseAuthentication(ASender: TIdContext;
      const AAuthType, AAuthData: String;
      var VUsername, VPassword: String): Boolean;
    begin
      if TextIsSame(AAuthType, 'Bearer') then begin
        // process AAuthData and assign VUsername and VPassword as needed...
        Result := True;
      end else
        Result := inherited DoParseAuthentication(ASender, AAuthType, AAuthData, VUsername, VPassword);
    end;