Return a custom auth response object from ServiceS

2019-02-09 06:03发布

问题:

Is it possible to return a custom auth response? I already have my own custom authentication provider that inherits from CredentialsAuthProvider.

I want to return the session expiry date in the response, so that the client knows exactly when their server session will expire:

{
    "sessionId": "bG27SdxbRkqJqU6xv/gvBw==",
    "userName": "joe.bloggs@letmein.com",
    "sessionExpires": "2013-04-29T03:27:14.0000000",
    "responseStatus": {}
}

I can override the Authenticate method like so:

public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
{
    // get base response
    var response = base.Authenticate(authService, session, request);

    // grab the session
    var customSession = authService.GetSession() as CustomUserSession;

    // if response can be cast and customSession exists
    if (response is AuthResponse && customSession != null)
    {
        // cast
        var authResponse = response as AuthResponse;

        // build custom response
        var customAuthResponse = new CustomAuthResponse
            {
                ReferrerUrl = authResponse.ReferrerUrl,
                SessionExpiry = customSession.SessionExpires,
                SessionId = authResponse.SessionId,
                ResponseStatus = authResponse.ResponseStatus,
                UserName = authResponse.UserName
            };
        return customAuthResponse;
    }

    // return the standard response
    return response;
}

This works fine, except in the case where the session already is active. In that case, the AuthService Post method checks for a valid session and automatically returns a standard AuthResponse, and there is no obvious way to override it:

var alreadyAuthenticated = response == null;
response = response ?? new AuthResponse {
    UserName = session.UserAuthName,
    SessionId = session.Id,
    ReferrerUrl = referrerUrl,
};

Following Paaschpa's ideas below, the following forces re-auth to always be re-authenticated, but it seems like there could be risks involved in leaving multiple active sessions open:

public override bool IsAuthorized(IAuthSession session, IOAuthTokens tokens, Auth request = null)
{
    // force re-authentication. Not great, but no other obvious way to do this
    if (request != null)
    {
        return false; // auth or re-auth calls
    }

    return base.IsAuthorized(session, tokens, request);
}

Can anyone think of a better way to do this? I could implement my own AuthenticationService, but I'm not sure how I would override the AuthFeature?

回答1:

If I understand correctly, you want to return a custom response after a user authenticates against '/auth/credentials'. Since you already have your own CredentialsAuthProvider I think you could just override Authenticate and return your own response.

Subclass of CredentialsAuthProvider

public class MyCredentialsAuthProvider : CredentialsAuthProvider
{
    public override object Authenticate(ServiceStack.ServiceInterface.IServiceBase authService, IAuthSession session, Auth request)
    {
        //let normal authentication happen
        var authResponse = (AuthResponse)base.Authenticate(authService, session, request);

        //return your own class, but take neccessary data from AuthResponse
        return new
            {
                UserName = authResponse.UserName,
                SessionId = authResponse.SessionId,
                ReferrerUrl = authResponse.ReferrerUrl,
                SessionExpires = DateTime.Now
            };

    }
}