How to correctly implement IUserSessionSource - ServiceStack

依然范特西╮ 提交于 2019-12-24 13:46:24

问题


A new feature has been added to ServiceStack 5.0 that allows for refreshTokens without an IAuthRepository, see here

I do not know of any documentation available for this new feature of ServiceStack 5.0, I have a Custom AuthProvider and I am not sure how to implement IUserSessionSource.

Currently, my IUserSessionSource.GetUserSession implementation is not even called and I have cleared my Nuget cache and retrieved the latest 5.0 libs from ServiceStacks Nuget server.

Here is my code:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider, IUserSessionSource
{
    private readonly ITsoContext _tsoContext;
    private IEnumerable<Claims> _claims;

    public CustomCredentialsAuthProvider(ITsoContext tsoContext)
    {
        _tsoContext = tsoContext;
    }

    public override bool TryAuthenticate(IServiceBase authService,
        string userName, string password)
    {
        _claims = _tsoContext.AuthenticateUser(userName, password);

        return _claims.Any();
    }

    /// <summary>
    /// ref: https://github.com/ServiceStack/ServiceStack/blob/a5bc5f5a96fb990b69dcad9dd5e95e688477fd94/src/ServiceStack/Auth/CredentialsAuthProvider.cs#L236
    /// ref: https://stackoverflow.com/questions/47403428/refreshtoken-undefined-after-successful-authentication-servicestack/47403514#47403514
    /// </summary>
    /// <param name="authService"></param>
    /// <param name="session"></param>
    /// <param name="tokens"></param>
    /// <param name="authInfo"></param>
    /// <returns></returns>
    public override IHttpResult OnAuthenticated(IServiceBase authService,
        IAuthSession session, IAuthTokens tokens,
        Dictionary<string, string> authInfo)
    {

        var customUserSession = (Framework.Auth.CustomUserSession) session;
        customUserSession.AuthProvider = "credentials";
        customUserSession.CreatedAt = DateTime.UtcNow;
        customUserSession.UserAuthId = _claims.First(item => item.ClaimName == "sub").ClaimValue;
        customUserSession.FirstName = _claims.First(item => item.ClaimName == "given_name").ClaimValue;
        customUserSession.LastName = _claims.First(item => item.ClaimName == "family_name").ClaimValue;
        customUserSession.Roles = _claims.First(item => item.ClaimName == "product_ids").ClaimValue.Split(",").ToList();
        customUserSession.Permissions = _claims.First(item => item.ClaimName == "product_feature_ids").ClaimValue.Split(",").ToList();
        customUserSession.Email = _claims.First(item => item.ClaimName == "email").ClaimValue;
        customUserSession.Company = _claims.First(item => item.ClaimName == "company_name").ClaimValue;
        customUserSession.ZipCode = _tsoContext.GetUserZip(customUserSession.UserAuthId);

        //https://stackoverflow.com/a/47403514/1258525
        //might not need this after correctly implementing IUserSessionSource
        authService.Request.Items[Keywords.DidAuthenticate] = true;

        //Call base method to Save Session and fire Auth/Session callbacks:
        return base.OnAuthenticated(authService, session, tokens, authInfo);
    }

    public IAuthSession GetUserSession(string userAuthId)
    {
        throw new NotImplementedException();
    }
}

回答1:


It should contain the same UserSession that your AuthProvider populates for an Authenticated User identified by userAuthId, which in your Custom AuthProvider matches the sub Claim Value.

You should create a new UserSession and try re-use the same code to populate the UserSession as being used in OnAuthenticated()

var customUserSession = new Framework.Auth.CustomUserSession();
customUserSession.AuthProvider = "credentials";
...

The IUserSessionSource is currently only invoked when using the RefreshToken to request a new JWT BearerToken, i.e.

/access-token?RefreshToken={RefreshToken}

I've just added a change where RefreshTokens are being populated when IUserSessionSource exists in this commit so if you clear your NuGet cache:

$ nuget locals all -clear

And restore the ServiceStack V5 packages from MyGet the RefreshToken should be populated on a successful Authentication Response and you will be able to manually call:

/access-token?RefreshToken={RefreshToken}

To retrieve a new JWT Token from your RefreshToken which is populated from the UserSession returned from GetUserSession().



来源:https://stackoverflow.com/questions/47441598/how-to-correctly-implement-iusersessionsource-servicestack

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!