Permissions issue

Hi, I’ve just updated to 5.13.2 and .Net 6 and it went smoothly apart from one issue:

I have a couple of unit tests that check that a request by a user with insufficient permissions returns a 403 error. This has been working fine for the past couple of years but now it is returning a 500.

Has something changed with regards to RequiredPermission?

Regards,
Alan

One change was that it was expected that the sessions UserAuthId is populated with the Users Id, if that’s the issue you can either populate UserAuthId or upgrade to v5.13.3 on MyGet which has reverted this requirement.

I tried using v5.13.3 but it still gives NullReferenceException.

What’s the full Exception StackTrace?

   at ServiceStack.ServiceClientBase.ThrowWebServiceException[TResponse](Exception ex, String requestUri) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 912
   at ServiceStack.ServiceClientBase.ThrowResponseTypeException[TResponse](Object request, Exception ex, String requestUri) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 847
   at ServiceStack.ServiceClientBase.HandleResponseException[TResponse](Exception ex, Object request, String requestUri, Func`1 createWebRequest, Func`2 getResponse, TResponse& response) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 799
   at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 1441
   at ServiceStack.ServiceClientBase.Put[TResponse](Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 1615
   at ServiceStack.ServiceClientBase.Send[TResponse](Object request) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 679
   at ServiceStack.ServiceGatewayExtensions.Send[TResponse](IServiceGateway client, IReturn`1 request) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceGatewayExtensions.cs:line 12
   at xxx<Update_WhenAuthenticated_ButDoesNotHavePermission>b__0() in C:\dev\xxx
   at Shouldly.Should.ThrowInternal[TException](Func`1 actual, String customMessage, String shouldlyMethod) in C:\projects\shouldly\src\Shouldly\ShouldStaticClasses\ShouldThrow.cs:line 71

That’s only the ServiceClient exception saying only that the server returned an error, can you provide either the Server Exception StackTrace or the raw HTTP Response Headers (with any sensitive info scrubbed out).

Sorry about the delay in replying.

FYI This is being handled as an AutoCRUD process (don’t know if that would matter).

The response header is:

{
   Date: Wed, 01 Dec 2021 11:40:41 GMT
   Server: Kestrel
   Set-Cookie: ss-id=xxx; path=/; samesite=lax; httponly, ss-pid=xxx; expires=Sun, 01 Dec 2041 11:40:41 GMT; path=/; samesite=lax; httponly, ss-opt=temp; expires=Sun, 01 Dec 2041 11:40:41 GMT; path=/; samesite=lax; httponly, X-UAId=5; expires=Sun, 01 Dec 2041 11:40:41 GMT; path=/; samesite=lax; httponly
   Transfer-Encoding: chunked
   Vary: Accept
   X-Powered-By: ServiceStack/5.133 NetCore/Windows/net6
   Content-Type: application/jsv
}

I have an UncaughtExceptionHandler in AppHost.Configure() but a breakpoint here doesn’t get hit.

When calling the API from Postman it returns a HTML page with the message:

"We're sorry <b>/api/currentLocalCoordinateSystem</b> is no longer here."

Importing the API into Postman shows it in the Collections.
I just went to check the /metadata and /swagger-ui pages to see if it still appears there but these pages no longer display.

The api has a signature of “/api/currentLocalCoordinateSystem/{Id}”.
The request object is:

[ ProtoContract ]
[ ValidateIsAuthenticated ]
[ RequiredPermission( "CanChangeCurrentLocalCoordinateSystem" ) ]
[ Route( "/api/currentLocalCoordinateSystem/{Id}", HttpMethods.Put ) ]
public class UpdateCurrentLocalCoordinateSystem : IUpdateDb< CurrentLocalCoordinateSystem >, IReturn< UpdateCurrentLocalCoordinateSystemResponse >, IHasIntId
{
  [ ProtoMember( 1 ) ]
  [ ApiMember( Name = ApiMemberName.NamedConnection, Description = ApiMemberDescription.NamedConnection, IsRequired = false ) ]
  public string NamedConnection { get; set; }

  [ ProtoMember( 2 ) ]
  [ ApiMember( Name = ApiMemberName.RowVersion, Description = ApiMemberDescription.RowVersion, IsRequired = true ) ]
  public ulong RowVersion { get; set; }

  [ ProtoMember( 3, DataFormat = DataFormat.ZigZag ) ]
  [ ApiMember( Name = "Id", Description = "The current local coordinate system identifier.", IsRequired = true ) ]
  public int Id { get; set; }

  [ ProtoMember( 4, DataFormat = DataFormat.ZigZag ) ]
  [ ApiMember( Name = "Local Coordinate System Id", Description = "The local coordinate system identifier.", IsRequired = true ) ]
  public int LocalCoordinateSystemId { get; set; }
}

I have noticed that when I call the API from Postman with the Id specified in the body (as I usually do), then the “no longer here” message is returned:

{
    "NamedConnection": "testdb",
    "RowVersion": 1,
    "Id": 1,
    "LocalCoordinateSystemId": 1000
}

but if I remove it from the body and add it to the url then it works.
Creating an UpdateCurrentLocalCoordinateSystem request object and sending via a ServiceStack Client now always fails.

Regards,
Alan

I really need some way to find out what the source of the Exception is, if not from the StackTrace then from the raw HTTP Response Errors which (in DebugMode) should contain the Server StackTrace serialized in the ResponseStatus property of the Response DTO.

Can you try logging the Exception (e.g. ex.ToString()) in both the Service and Uncaught Exception handlers.

If for some reason that doesn’t print out the StackTrace can you then use Chrome’s Web Inspector to make the same request and screenshot the Headers tab and copy the contents of the Response tab here which should contain the error response body.

You can make the Ajax request by typing F12 on the browser tab of one of your Apps page then paste in the URL you’re trying to call, you can force a json response with the .json ext, e.g:

Easy Copy + Paste:

await (await fetch('/api/currentLocalCoordinateSystem.json')).json()

Then click on the request in the Network Tab, to get the contents of the Headers and Response tabs.

System.NullReferenceException: Object reference not set to an instance of an object.
   at ServiceStack.AuthUserSession.HasAllPermissionsAsync(ICollection`1 requiredPermissions, IAuthRepositoryAsync authRepo, IRequest req, CancellationToken token) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthUserSession.cs:line 158
   at ServiceStack.RequiredPermissionAttribute.HasAllPermissionsAsync(IRequest req, IAuthSession session, ICollection`1 requiredPermissions, CancellationToken token) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\RequiredPermissionAttribute.cs:line 92
   at ServiceStack.RequiredPermissionAttribute.HasAllPermissionsAsync(IRequest req, IAuthSession session, ICollection`1 requiredPermissions, CancellationToken token) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\RequiredPermissionAttribute.cs:line 92
   at ServiceStack.RequiredPermissionAttribute.ExecuteAsync(IRequest req, IResponse res, Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\RequiredPermissionAttribute.cs:line 43
   at ServiceStack.ServiceStackHost.ApplyRequestFiltersSingleAsync(IRequest req, IResponse res, Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 181
   at ServiceStack.ServiceStackHost.ApplyRequestFiltersAsync(IRequest req, IResponse res, Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 145
   at ServiceStack.Host.Handlers.GenericHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\GenericHandler.cs:line 56

This looks like the HasAllPermissionsAsync() API was passed a null requiredPermissions:

Which is not clear how it was null, can you override HasAllPermissionsAsync in your Custom User Session, e.g:

public class CustomAuthSession : AuthUserSession
{
    public override Task<bool> HasAllPermissionsAsync(ICollection<string> requiredPermissions, IAuthRepositoryAsync authRepo, IRequest req,
        CancellationToken token = default)
    {
        var allPerms = await GetPermissionsAsync(authRepo, token).ConfigAwait();
        // put breakpoint & check args
        return base.HasAllPermissionsAsync(requiredPermissions, authRepo, req, token);
    }
}

Then put a breakpoint so you can check the state of each of the args and let me know which was null. If you can can you go debug or go up the callstack to find out why it was null as well thanks.

FYI: I’ve added null checks on each of these AuthUserSession APIs in this commit so the Exception should be clearer when its required arguments are null.

None of the incoming parameters are null, but the “allPerms” result from GetPermissionsAsync() is null.

The “requiredPermissions” collection contains a single item which is the expected “CanChangeCurrentLocalCoordinateSystem” permission, authRepo correctly references my security db and I can’t see anything obviously out of the ordinary with req.

What Auth Repository are you using?

It is an OrmLiteAuthRepository referencing a separate sqlite db.

Thanks, the NRE should be resolved from this commit. This change is available from the latest v5.13.1+ that’s now available on MyGet.

As you already have v5.13.1 installed you’ll need to clear your NuGet packages cache.

Okay, I’ll give that a try. Thanks for you help.

1 Like