Возвратите больше информации клиенту, используя генерацию токенов-маркеров OAuth и Owin в WebApi - программирование
Подтвердить что ты не робот

Возвратите больше информации клиенту, используя генерацию токенов-маркеров OAuth и Owin в WebApi

Я создал приложение WebApi и приложение для Кордовы. Я использую http-запросы для связи между приложением Cordova и WebApi. В WebApi я реализовал генерацию токенов-носителей OAuth.

public void ConfigureOAuth(IAppBuilder app)
    {
        var oAuthServerOptions = new OAuthAuthorizationServerOptions
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider(new UserService(new Repository<User>(new RabbitApiObjectContext()), new EncryptionService()))
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }

и это находится внутри реализации SimpleAuthorizationServerProvider

 public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
       context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        // A little hack. context.UserName contains the email
        var user = await _userService.GetUserByEmailAndPassword(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "Wrong email or password.");
            return;
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);
    }

после успешного входа в API из приложения Cordova, я получаю следующий JSON

{"access_token":"some token","token_type":"bearer","expires_in":86399}

Проблема заключается в том, что мне требуется дополнительная информация о пользователе. Например, у меня есть поле UserGuid в базе данных, и я хочу отправить его в приложение Cordova, когда логин будет успешным, и использовать его позже в других запросах. Могу ли я включить другую информацию для возврата клиенту, кроме "access_token", "token_type" и "expires_in"? Если нет, как я могу получить пользователя в API на основе access_token?


EDIT:

Я думаю, что нашел обходное решение. Я добавил следующий код внутри GrantResourceOwnerCredentials

identity.AddClaim(new Claim(ClaimTypes.Name, user.UserGuid.ToString()));

и после этого я обращаюсь к указателю внутри моего контроллера следующим образом: User.Identity.Name

Я также могу добавить guid с пользовательским именем identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));

Мне все еще интересно узнать, есть ли способ вернуть больше данных клиенту с маркером-носителем JSON.

4b9b3361

Ответ 1

Вы можете добавить столько заявок, сколько хотите.
Вы можете добавить стандартный набор претензий от System.Security.Claims или создать свой собственный.
Претензии будут зашифрованы в вашем токену, поэтому они будут доступны только с сервера ресурсов.

Если вы хотите, чтобы ваш клиент мог читать расширенные свойства вашего токена, у вас есть еще один вариант: AuthenticationProperties.

Предположим, вы хотите добавить что-то, чтобы ваш клиент мог получить доступ. Это путь:

var props = new AuthenticationProperties(new Dictionary<string, string>
{
    { 
        "surname", "Smith"
    },
    { 
        "age", "20"
    },
    { 
    "gender", "Male"
    }
});

Теперь вы можете создать билет со свойствами, которые вы добавили выше:

var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);

Результат, полученный вашим клиентом:

.expires: "Tue, 14 Oct 2014 20:42:52 GMT"
.issued: "Tue, 14 Oct 2014 20:12:52 GMT"
access_token: "blahblahblah"
expires_in: 1799
age: "20"
gender: "Male"
surname: "Smith"
token_type: "bearer"

С другой стороны, если вы добавите претензии, вы сможете прочитать их на своем сервере ресурсов в своем контроллере API:

public IHttpActionResult Get()
{
    ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

    return Ok();
}

Ваш ClaimsPrincipal будет содержать ваше новое требование guid, которое вы добавили здесь:

identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));

Если вы хотите узнать больше о owin, токенах-носителях и веб-api, там действительно хороший учебник здесь и эта статья поможет вам понять все концепции сервера авторизации и сервера ресурсов.

UPDATE

Здесь вы можете найти рабочий пример . Это веб-Api + Owin самостоятельно. Здесь нет базы данных. Клиент является консольным приложением (там также пример html + JavaScript), который вызывает учетные данные Web Api.

Как предложил Тайзер, вам нужно переопределить TokenEndpoint:

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
}

Включите "Несколько проектов запуска" из "Решение" → "Свойства", и вы можете запустить его сразу.

Ответ 2

Моя рекомендация - не добавлять лишние требования к токену, если это не нужно, потому что увеличит размер токена, и вы будете продолжать отправлять его с каждым запросом. Как рекомендовал LeftyX добавить их как свойства, но убедитесь, что вы переопределили метод TokenEndPoint, чтобы получить эти свойства в качестве ответа при получении маркера успешно, без этой конечной точки свойства не возвращаются в ответ.

 public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

        return Task.FromResult<object>(null);
    }

Здесь вы можете проверить мое репо для полного примера. Надеюсь, это поможет.