2017-08-09 111 views
0

我在WebApi中實現IdentityServer3令牌授權時遇到了問題。我的解決方案有一個.NET Core Angular 4客戶端項目和一個單獨的.NET Framework 4.5.2 WebApi項目。在添加令牌授權之前,WebApi已經過測試並正在運行。 IdentityServer3登錄和身份驗證也正常工作。我正在使用angular-auth-oidc-client節點模塊。我已驗證請求標題正在獲取爲Content-Type,Accept和Authorization設置的指定屬性。這是一些關鍵文件的代碼。IdentityServer3 + Angular4 + WebApi導致401未授權

用戶list.component.ts

import { Component, OnInit } from '@angular/core'; 
import { Http, Headers, Response } from '@angular/http'; 
import { Subject } from 'rxjs/Rx'; 
import { OidcSecurityService } from 'angular-auth-oidc-client'; 

import 'rxjs/add/operator/map'; 

class User { 
    userId: number; 
    firstName: string; 
    middleName: string; 
    lastName: string; 
    email: string; 
} 

@Component({ 
    selector: 'user-list', 
    templateUrl: './user-list.html', 
    styleUrls: ['./user-list.css'] 
}) 
export class UserListComponent implements OnInit { 
    dtOptions: DataTables.Settings = {}; 
    users: User[] = []; 

    dtTrigger: Subject<User> = new Subject(); 

    constructor(private http: Http, private securityService: OidcSecurityService) { } 

    ngOnInit(): void { 
     this.dtOptions = { 
      searching: true, 
      pagingType: 'full_numbers', 
      pageLength: 5, 
      info: false, 
      lengthChange: false 
     }; 

     let headers = new Headers(); 
     headers.append('Content-Type', 'application/json'); 
     headers.append('Accept', 'application/json'); 
     headers.append('Authorization', 'Bearer ' + this.securityService.getToken()); 

     //this.dtOptions = this.http.get('api/settings/datatables') 
     // .toPromise() 
     // .then(response => response.json()); 

     this.http.get('/api/home', { headers }) 
      .map((response: Response) => response.json()) 
      .subscribe(users => { 
       this.users = users; 
       this.dtTrigger.next(); 
      }); 
    } 
} 

app.module.ts

import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { HttpModule } from '@angular/http'; 
import { AppRoutingModule } from './app.routes'; 
import { DataTablesModule } from 'angular-datatables'; 

import { AppComponent } from './app.component'; 
import { UserListComponent } from './user-list/user-list.component'; 
import { PostalCodeComponent } from './postal-code/postal-code.component'; 

import { AuthModule, OidcSecurityService, OpenIDImplicitFlowConfiguration } from 'angular-auth-oidc-client'; 

@NgModule({ 
    declarations: [ 
     AppComponent, 
     UserListComponent, 
     PostalCodeComponent 
    ], 
    imports: [ 
     BrowserModule, 
     AppRoutingModule, 
     HttpModule, 
     DataTablesModule, 
     AuthModule.forRoot() 
    ], 
    providers: [OidcSecurityService], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { 
    constructor(public oidcSecurityService: OidcSecurityService) { 
     let settings = new OpenIDImplicitFlowConfiguration(); 
     settings.stsServer = 'https://identitydev.company.com/oidc/core'; 
     settings.redirect_url = 'http://localhost:4200'; 
     settings.client_id = '802523112846585'; 
     settings.response_type = 'id_token token'; 
     settings.scope = 'openid app_profile app_client_api'; 
     settings.post_logout_redirect_uri = 'http://localhost:4200'; 
     settings.startup_route = '/'; 
     //settings.forbidden_route = '/Forbidden'; 
     //settings.unauthorized_route = '/Unauthorized'; 
     settings.log_console_warning_active = true; 
     settings.log_console_debug_active = true; 
     //settings.max_id_token_iat_offset_allowed_in_seconds = 10; 
     //settings.override_well_known_configuration = true; 
     //settings.override_well_known_configuration_url = 'https://localhost:44386/wellknownconfiguration.json'; 

     // this.oidcSecurityService.setStorage(localStorage); 
     this.oidcSecurityService.setupModule(settings); 
    } 
} 

Startup.cs

using Microsoft.Owin; 
using Owin; 
using System.Web.Http; 
using IdentityServer3.AccessTokenValidation; 
using System.Net.Http.Headers; 
using Microsoft.Owin.Security.OAuth; 

[assembly: OwinStartup(typeof(App.API.Test.Startup))] 
namespace App.API.Test 
{ 
    public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions 
      { 
       Authority = "https://identitydev.company.com/oidc/core", 
       //RequiredScopes = new[] { "app_client_api" }, 
       ValidationMode = ValidationMode.ValidationEndpoint 
      }); 

      // configure web api 
      var config = new HttpConfiguration(); 
      config.MapHttpAttributeRoutes(); 
      config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
      app.UseWebApi(config); 
     } 
    } 
} 

個HomeController.cs

using System.Collections.Generic; 
using System.Security.Claims; 
using System.Web.Http; 
using TRAX.Models; 

namespace App.API.Test.Controllers 
{ 
    [Authorize] 
    [Route("api/home")] 
    public class HomeController : ApiController 
    { 
     [HttpGet] 
     public IEnumerable<User> Get() 
     { 
      UserList list = new UserList(); 
      return list.GetAll; 
     } 

     //// GET api/home/{firstname} 
     //[HttpGet("{FirstName}")] 
     //public List<User> GetByFirstName(string FirstName) 
     //{ 
     // UserList list = new UserList(); 
     // return list.GetUserByFirstName(FirstName); 
     //} 
    } 
} 

**注:沒有與此控制器返回數據進入模型,但你可以相信,它返回正確的列表。

回答

0

顯然,解決方案是刪除Microsoft在模板項目中創建的Global.ascx文件。然後,我更新了Startup.cs文件。

using Microsoft.Owin; 
using Owin; 
using System.Web.Http; 
using IdentityServer3.AccessTokenValidation; 

[assembly: OwinStartup(typeof(App.API.Test.Startup))] 
namespace App.API.Test 
{ 
    public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      HttpConfiguration config = new HttpConfiguration(); 

      app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions 
      { 
       Authority = "https://identitydev.company.com/oidc/core", 
       RequiredScopes = new[] { "app_client_api" }, 
       ValidationMode = ValidationMode.ValidationEndpoint 
      }); 

      WebApiConfig.Register(config); 
      app.UseWebApi(config); 
     } 
    } 
} 

我也不需要在客戶端API調用中包含Content-Type或Accept標頭覆蓋。我從WebApi默認返回JSON。