2015-01-12 12 views
16

Tôi đã làm theo hướng dẫn để bảo vệ API Web với OAuth trong C#.Điểm cuối API trả lại "Ủy quyền đã bị từ chối cho yêu cầu này". khi gửi mã thông báo mang số

Tôi đang thực hiện một số thử nghiệm và cho đến nay tôi đã có thể nhận được mã thông báo truy cập thành công từ /token. Tôi đang sử dụng một tiện ích mở rộng của Chrome có tên là "Khách hàng REST nâng cao" để kiểm tra nó.

{"access_token":"...","token_type":"bearer","expires_in":86399} 

Đây là những gì tôi nhận được từ /token. Mọi thứ trông có vẻ tốt.

yêu cầu tiếp theo của tôi là để điều khiển API thử nghiệm của tôi:

namespace API.Controllers 
{ 
    [Authorize] 
    [RoutePrefix("api/Social")] 
    public class SocialController : ApiController 
    { 
     .... 


     [HttpPost] 
     public IHttpActionResult Schedule(SocialPost post) 
     { 
      var test = HttpContext.Current.GetOwinContext().Authentication.User; 

      .... 
      return Ok(); 
     } 
    } 
} 

Yêu cầu là một POST và có tiêu đề:

Authorization: Bearer XXXXXXXTOKEHEREXXXXXXX 

tôi nhận được: Authorization has been denied for this request. trả lại trong JSON.

Tôi đã thử thực hiện GET và tôi nhận được những gì tôi mong đợi, rằng phương pháp này không được hỗ trợ vì tôi không triển khai nó.

Đây là nhà cung cấp ủy quyền của tôi:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider 
{ 
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
    { 
     context.Validated(); 
    } 

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 

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

     using (var repo = new AuthRepository()) 
     { 
      IdentityUser user = await repo.FindUser(context.UserName, context.Password); 

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

     var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
     identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 
     identity.AddClaim(new Claim(ClaimTypes.Role, "User")); 

     context.Validated(identity); 

    } 
} 

Bất kỳ trợ giúp sẽ là tuyệt vời. Tôi không chắc đó có phải là yêu cầu hay mã sai.

chỉnh sửa: Đây là tôi Startup.cs

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     var config = new HttpConfiguration(); 
     WebApiConfig.Register(config); 
     app.UseWebApi(config); 
     ConfigureOAuth(app); 
    } 

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

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

    } 
} 

Trả lời

27

Issue là khá đơn giản: Thay đổi thứ tự của đường ống OWIN bạn.

public void Configuration(IAppBuilder app) 
{ 
    ConfigureOAuth(app); 
    var config = new HttpConfiguration(); 
    WebApiConfig.Register(config); 
    app.UseWebApi(config); 
} 

Đối với thứ tự đường ống OWIN của cấu hình của bạn khá quan trọng. Trong trường hợp của bạn, bạn cố gắng sử dụng trình xử lý API Web của bạn trước trình xử lý OAuth. Bên trong của nó, bạn xác nhận yêu cầu của bạn, tìm thấy bạn an toàn hành động và cố gắng xác nhận nó chống lại hiện tại Owin.Context.User. Tại thời điểm này người dùng này không tồn tại bởi vì thiết lập của nó từ mã thông báo với OAuth Handler được gọi sau.

+0

Làm thế nào bạn sẽ làm điều này nếu bạn không đăng ký WebApi trong đường ống? Tôi chỉ đang làm việc với mẫu API Web mặc định. Yêu cầu GET hoạt động tốt, yêu cầu POST cung cấp cho tôi 401. Trong khi mã thông báo giống nhau. – mwijnands

+1

Điều này khiến tôi hiểu! Cảm ơn bạn đã dành thời gian đăng câu trả lời này. – heymega

+0

Tôi lãng phí vài giờ sau khi tái cấu trúc cố gắng tìm một lý do cho vấn đề này. – Tomino

2

Bạn cần phải thêm một tuyên bố với schema này:

http://schemas.microsoft.com/ws/2008/06/identity/claims/role 

điều tốt nhất để làm là sử dụng các thiết lập được xác định trước các tuyên bố:

identity.AddClaim(new Claim(ClaimTypes.Role, "User")); 

Bạn có thể tìm thấy ClaimTypes trong System.Security.Claims.

Một điều bạn cần phải xem xét là vai trò bộ lọc trong điều khiển của bạn/Hành động:

[Authorize(Roles="User")] 

Bạn có thể tìm thấy một ứng dụng mẫu đơn giản, tự lưu trữ owin với một khách hàng jquery here.

+0

Tôi đã thêm: 'identity.AddClaim (xác nhận quyền sở hữu mới (ClaimTypes.Role," User "));' không có kết quả. Liệu người dùng có phải là vốn không? Tôi đã thêm điều này trước khi tôi nhìn thấy bình luận của bạn. Tôi sẽ không nghĩ rằng đó sẽ là vấn đề. Tôi sẽ kiểm tra liên kết của bạn. –

+0

Đó là một hằng số và có thể là bất cứ điều gì. – LeftyX

+0

Tôi đã thử thay đổi '[Ủy quyền]' để bao gồm vai trò trong bộ điều khiển của tôi, nhưng tôi vẫn không nhận được nó để cho phép. Tôi đã tạo một người dùng mới trong vai trò "Người dùng" và nhận được một mã thông báo mới thành công. Đã cập nhật mã của tôi ở trên với thay đổi được đề xuất của bạn. –

0

Có vẻ như phiên bản "System.IdentityModel.Tokens.Jwt" đồng tồn tại với các hội đồng Owin khác không đúng.

Trong trường hợp bạn đang sử dụng "Microsoft.Owin.Security.Jwt" phiên bản 2.1.0, bạn nên sử dụng phiên bản "System.IdentityModel.Tokens.Jwt" phiên bản 3.0.2.

Từ gói quản lý giao diện điều khiển, hãy thử:

Update-Package System.IdentityModel.Tokens.Jwt -Version 3.0.2 
Các vấn đề liên quan