Delphi DataSnap authorization not repecting TRoleAuth attribute
Asked Answered
D

1

5

I am trying to implement authorization in a Delphi XE DataSnap application. I broke this down into a very simple example, but still do not see the effects of the TRoleAuth attribute for a method or class.

Here is a simple DSServerMethods class that includes the generated sample methods. The class has been decorated with the guest and anyone authorized roles, and the unwelcome denied role. The ReverseString method has been decorated with the readonly denied role:

type
  [TRoleAuth('guest,anyone','unwelcome')]
  TMyDSServerMethods = class(TDSServerModule)
    DataSetProvider1: TDataSetProvider;
  ...
  public
    { Public declarations }
    function EchoString(Value: string): string;
    [TRoleAuth('','readonly')]
    function ReverseString(Value: string): string;
    ...
  end;

I am assigning roles on the OnUserAuthenticate method. For example, I have a user for whom I am assigning the readonly role from OnUserAuthenticate, a role which I believe should deny that user permission to execute the ReverseString function.

From what I understand, my code should compare the user's roles against the EventObject.AuthorizedRoles and EventObject.DeniedRoles TStrings from the OnUserAuthorize method of the TDSAuthenticationManager, and set the valid formal parameter of this method accordingly.

Here is a simple OnUserAuthorize method I am using for tesing. When I step into it using the debugger in response to a user with the readonly role attempting to invoke ReverseString, EventObject.AuthorizedRoles and EventObject.DeniedRoles are both nil, and EventObject.Roles contains the readonly role.

procedure TServerContainer1.DSAuthenticationManager1UserAuthorize(
  Sender: TObject; EventObject: TDSAuthorizeEventObject;
  var valid: Boolean);
begin
  outputdebugstring(PChar(Eventobject.UserName));
  if EventObject.UserRoles <> nil then
    outputdebugstring(PChar(eventobject.UserRoles.Text));
  if EventObject.AuthorizedRoles <> nil then
    outputdebugstring(PChar(eventobject.AuthorizedRoles.Text));
  if EventObject.DeniedRoles <> nil then
    outputdebugstring(PChar(eventobject.DeniedRoles.Text));
  valid := True;
end;

Am I missing the point, or is there a property that I need to set somewhere to enable the TRoleAuth attribute to function?

= = = = = = = = = = Edit: Mat DeLong provided the answer. The DSAuth unit (where the TRoleAuth custom attribute class is declared) was missing from the interface section of the unit in which the DSServerModule descendant was defined.

Dawn answered 18/3, 2011 at 16:15 Comment(0)
S
10

One thing to make sure of is that in your server methods class you have the "DSAuth" unit in the uses clause of the interface section. If you don't, you should see a compile time warning saying "Unsupported language feature: ‘custom attribute’". If this is happening, it means your attributes are being ignored because the TRoleAuth type is unknown.

If that isn't the case, then I'm not sure what else it would be. If working properly, in your OnUserAuthorize event, you should see "EventObject.DeniedRoles" containing the "readonly" role defined in the code attribute. You should also see "EventObject.UserRoles" containing this role. If this is the case, then you wouldn't need to implement OnUserAuthorize at all, and the code would automatically deny this user authorization.

A couple things to note:

  • If you put a TRoleAuth attribute on a function or procedure, it replaces the attribute put on the class (only for that one method.) It doesn't add to it.

  • If you set a design-time attribute that ends up apply to the method (by modifying the 'Roles' collection on the TDSAuthenticationManager component) then the attribute(s) you added in code will be ignored.

Hope that helps,

Mat

Scalf answered 18/3, 2011 at 18:51 Comment(6)
"Unsupported language feature"? The Delphi compiler talks in obscure language :)Ulland
Bingo! The DSAuth unit did not appear in the interface (or implementation section) uses clause of the DSServerModule. As soon as I put it in the TRoleAuth attribute did its job.Dawn
@mjn: Delphi's compiler messages tend to be extremely clear and easy to understand, usually. This one is of the few exceptions.Lifeordeath
What would a better message be? Warning: Your attributes have been removed from the compiled code, because you need to enable this optional attribute feature somehow? I am not sure how adding DSAuth enables these attributes. There must be some kind of "pragma" in there that defines this particular attribute and allows it to compile without a warning?Apocrypha
+1 Nice, this role auth is a toy I want to play with a bit in the next months, and Welcome to SO, @Mat. :)Simitar
Warren: DSAuth doesn't enable custom attributes. Custom attributes just work. But if you want to use the TRoleAuth attribute, that is a class which lives in the DSAuth unit. (TRoleAuth = class(TCustomAttribute)) And thanks for the welcome, all :)Scalf

© 2022 - 2024 — McMap. All rights reserved.