1

У меня есть требование, как показано ниже, для реализации REST API с использованием OAuth 2.0 и Web Api.Как реализовать REST API с OAuth 2.0 для множественного доступа клиентов

REST API должен позволять - создавать, обновлять, просматривать и удалять заказы - создавать, обновлять, просматривать и удалять товарно-материальные запасы

API должен быть в состоянии использоваться любым типом внешнего клиента, такие как веб-приложения , мобильное приложение, окна/веб-службы и т. д.

Роли, разрешенные для внешних клиентов: управление заказами, управление запасами Пользовательские данные (роли, разрешения) внешних клиентов не будут управляться нашей системой.

Примечание: Могут быть две другие роли, такие как Internal, External. Потому что функции удаления не могут быть разрешены для внешних пользователей.

Данные для заказа и инвентаризации будут управляться в базе данных SQL Server, которая уже используется текущими приложениями Windows/Desktop. Заказы, запасы, поступающие через новый API, должны сохраняться в одной базе данных.

Вопросы:

  1. Какой грант типа я могу использовать?
  2. Как мне управлять данными внешнего клиента (разрешенные роли, идентификатор клиента, токены)? Нужно ли для этого использовать отдельную базу данных членства? Могу ли я использовать для этого существующую базу данных с новыми таблицами?
+0

Посмотрите, может ли наш asnwer помочь с http://stackoverflow.com/questions/38424518/use-web-api-cookie-for-mvc-cookie/38428420#38428420 –

ответ

2

Вы можете использовать Microsoft.Owin.Security.OAuth провайдер. Пожалуйста, смотрите следующий образец.

Создать новый файл Owin Startup и изменить метод Configuration следующим

public void Configuration(IAppBuilder app) 
{ 
    var oauthProvider = new OAuthAuthorizationServerProvider 
    { 
     OnGrantClientCredentials = async context => 
     { 

      var claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType); 
      // based on clientId get roles and add claims 
      claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Developer")); 
      claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Developer2")); 
      context.Validated(claimsIdentity); 
     }, 
     OnValidateClientAuthentication = async context => 
     { 
      string clientId; 
      string clientSecret; 
      // use context.TryGetBasicCredentials in case of passing values in header 
      if (context.TryGetFormCredentials(out clientId, out clientSecret)) 
      { 
       if (clientId == "clientId" && clientSecret == "secretKey") 
       { 
        context.Validated(clientId); 
       } 
      } 
     } 
    }; 
    var oauthOptions = new OAuthAuthorizationServerOptions 
    { 
     AllowInsecureHttp = true, 
     TokenEndpointPath = new PathString("/accesstoken"), 
     Provider = oauthProvider, 
     AuthorizationCodeExpireTimeSpan = TimeSpan.FromMinutes(1), 
     AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(3), 
     SystemClock = new SystemClock() 
    }; 
    app.UseOAuthAuthorizationServer(oauthOptions); 
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 

    var config = new HttpConfiguration(); 
    config.MapHttpAttributeRoutes(); 
    app.UseWebApi(config); 
} 

и авторизовать API как этот

[Authorize(Roles = "Developer")] 
// GET: api/Tests 
public IEnumerable<string> Get() 
{ 
    return new string[] { "value1", "value2" }; 
} 

вы можете потреблять его, как следующий,

string baseAddress = "http://localhost/"; 
var client = new HttpClient(); 

// you can pass the values in Authorization header or as form data 
//var authorizationHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes("clientId:secretKey")); 
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationHeader); 

var form = new Dictionary<string, string> 
    { 
     {"grant_type", "client_credentials"}, 
     {"client_id", "clientId"}, 
     {"client_secret", "secretKey"}, 
    }; 

var tokenResponse = client.PostAsync(baseAddress + "accesstoken", new FormUrlEncodedContent(form)).Result; 
var token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result; 
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken); 
var authorizedResponse = client.GetAsync(baseAddress + "/api/Tests").Result; 

Токен.CS

internal class Token 
{ 
    [JsonProperty("access_token")] 
    public string AccessToken { get; set; } 

    [JsonProperty("token_type")] 
    public string TokenType { get; set; } 

    [JsonProperty("expires_in")] 
    public int ExpiresIn { get; set; } 

    [JsonProperty("refresh_token")] 
    public string RefreshToken { get; set; } 
} 

ответы на вопросы

  1. Вы можете использовать client_credentials
  2. Ведение ролей в своей собственной базе данных для каждого клиента и внутри OnGrantClientCredentials просто получить роли по идентификатором клиента и назначить в качестве претензий.
1
  1. Here является отправной точкой, которая Грант выбрать, для которого клиент. Кроме того, если вы создаете SPA (даже это первый участник в соответствии с формулировкой из ссылки), я бы предпочел неявный грант. Если у вас есть вопрос о конкретном Гранте для конкретного Клиента, создайте новый вопрос о stackoverflow.

  2. Вы можете использовать IdentityServer3 с IdentityServer3.EntityFramework и IdentityServer3.AspNetIdentity. Вы можете размещать таблицы IdentityServer в существующей базе данных, но я бы не рекомендовал его для производства.