[英]IdentityServer3 + Angular4 + WebApi Causing 401 Unauthorized
I am having trouble with implementing IdentityServer3 token authorization in my WebApi. 我在WebApi中实现IdentityServer3令牌授权时遇到麻烦。 My solution has a .NET Core Angular 4 client side project and a separate .NET Framework 4.5.2 WebApi project.
我的解决方案有一个.NET Core Angular 4客户端项目和一个单独的.NET Framework 4.5.2 WebApi项目。 The WebApi has been tested and is working before adding the token authorization.
在添加令牌授权之前,WebApi已经过测试并且可以正常工作。 The IdentityServer3 login and authentication is working as well.
IdentityServer3登录和身份验证也正常工作。 I am using the angular-auth-oidc-client node module.
我正在使用angular-auth-oidc-client节点模块。 I have verified that the Request Header is getting the designated properties set for Content-Type, Accept and Authorization.
我已验证请求标头是否正在为Content-Type,Accept和Authorization设置指定的属性。 Here is the code for some of the key files.
这是一些关键文件的代码。
user-list.component.ts 用户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 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 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 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);
//}
}
}
** Note: There is a model that goes with this controller to return the data but you can trust that it is returning the correct list. **注意:该控制器附带一个模型来返回数据,但是您可以相信它会返回正确的列表。
Apparently the solution was to remove the Global.ascx file that Microsoft created in the template project. 显然,解决方案是删除Microsoft在模板项目中创建的Global.ascx文件。 I then updated the Startup.cs file as such.
然后,我就这样更新了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);
}
}
}
I also did not need to include the Content-Type or Accept header overrides from the client side API call. 我也不需要从客户端API调用中包含Content-Type或Accept标头替代。 I return JSON by default from the WebApi.
默认情况下,我从WebApi返回JSON。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.