簡體   English   中英

.Net Web API 2,OWIN和OAuth:范圍和角色。 有什么區別?

[英].Net Web API 2, OWIN, and OAuth: Scopes and roles. What are the differences?

我想在腦海中創建一個更清晰的圖片,了解.NET Web API項目中角色和范圍之間的差異。 這是一個最好的方法問題而不是其他任何問題,我發現自己對如何最好地授權想要訪問我的API的用戶感到困惑。 我來自.NET MVC背景,所以我熟悉角色,我想知道相同的方法是否適用於Web API框架。 我很難將范圍放在圖片中,以及如何使用它們來允許使用特定客戶端ID的用戶進行訪問。 范圍是否與訪問權限類似? 為了說明我的困惑,讓我們使用這個例子:

Client A
Native app: displays event calendar
Role: Event
User login required? No
Allowed scopes: Read events

Client B
Web app: shows next upcoming event, displays registrant names
Role: Event
User login required? Yes
Allowed scopes: Read events, read registrants

Client C
Native app: registers a person for an event
Role: Registrant
User login required? Yes
Allowed scopes: Read events, read registrants, write registrants

基本上我想知道我上面使用的范圍是否正確以及授予資源所有者憑據的最佳方法是什么。 我正在使用Taiseers教程中概述的基於令牌的身份驗證。 以下是我目前不完整的代碼片段,它將負責驗證所請求的客戶端和范圍:

public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
    ApiClient client = null;
    string clientId = string.Empty;
    string clientSecret = string.Empty;

    if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
        context.TryGetFormCredentials(out clientId, out clientSecret);

    if (context.ClientId == null)
    {
        context.Validated();
        context.SetError("invalid_clientId", "ClientId should be sent.");
        return Task.FromResult<object>(null);
    }

    using (ApiClientRepo _clientRepo = context.OwinContext.GetUserManager<ApiClientRepo>())
    {
        client = _clientRepo.FindClient(context.ClientId);
    }

    if (client == null)
    {
        context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", context.ClientId));
        return Task.FromResult<object>(null);
    }

    // Validate client secret

    if (string.IsNullOrWhiteSpace(clientSecret))
    {
        context.SetError("invalid_secret", "Client secret should be sent.");
        return Task.FromResult<object>(null);
    }
    else
    {
        WPasswordHasher passwordHasher = new WPasswordHasher();
        PasswordVerificationResult passwordResult = passwordHasher.VerifyHashedPassword(client.SecretHash, clientSecret);

        if (passwordResult == PasswordVerificationResult.Failed)
        {
            context.SetError("invalid_secret", "Client secret is invalid.");
            return Task.FromResult<object>(null);
        }
    }

    if (!client.Active)
    {
        context.SetError("invalid_clientId", "Client is inactive.");
        return Task.FromResult<object>(null);
    }

    context.OwinContext.Set<int>("as:clientRepoId", client.Id);
    context.OwinContext.Set<string>("as:clientAllowedOrigin", client.AllowedOrigin);
    context.OwinContext.Set<string>("as:clientRefreshTokenLifeTime", client.RefreshTokenLifeTime.ToString());

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

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    IApiUser user = null;
    string scope = null;

    // Get parameters sent in body
    Dictionary<string, string> body = context.Request.GetBodyParameters();

    // Get API scope
    body.TryGetValue("scope", out scope);

    if (scope == null)
    {
        context.Validated();
        context.SetError("invalid_scope", "Invalid requested scope.");
        return;
    }

    var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");

    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });    

    // At this point I got the requested scope.
    // What should I do with it?

    if (user == null)
    {
        context.SetError("invalid_grant", "The user name or password is incorrect.");
        return;
    }      

    // create claims identity based on user info
    ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType);
    identity.AddClaim(new Claim(ClaimTypes.Name, user.FirstName + " " + user.LastName));
    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Username));
    identity.AddClaim(new Claim(ClaimTypes.Role, scope));

    var props = new AuthenticationProperties(new Dictionary<string, string>
        {
            { 
                "as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId
            },
            { 
                "userName", context.UserName
            }
        });

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

感謝所有的想法,建議和想法!

在我看來,范圍定義了資源。 基本上,請求挑戰是“may client(= application)代表您訪問資源x”?

其中x是您的API所服務的任何資源。 我在一個項目中使用了一個方便,其中范圍可以特定於資源上的CRUD操作。 例如scope = tweets.read或tweets.create。

擁有范圍的令牌不會給客戶端許可。 該權限基於以下事實:用戶有權執行操作並使客戶端在其令牌中具有正確的資源范圍。 當然,用戶權限可以基於訪客或管理員等角色。

因此理論上,用戶可以授予對其沒有權限的范圍(資源)的訪問權限。

令牌的生命周期為20分鍾,如果您根據訪問令牌中的任何值建立權限,則權限不能在令牌生存期內被撤銷或更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM