OAuth2 Adal Angularjs Web APi 功能出现问题 - Web APi 未授权
Having Problems with OAuth2 Adal Angularjs Web APi functionality - Web APi not Authorizing
因此,我又一次不得不留下大量时间来研究安全性。
我非常想了解如何让我的 AngularJS SPA 能够通过安全的环境调用我的 API。
我很难掌握的是我认为的安全令牌的路径。
因此,在 Azure Active Directory 开发人员指南中的 Microsoft 指南之一的帮助下,我已经设法使用 OAuth2 保护我的 AngularJS SPA。
我现在可以登录并获得进入 SPA 的授权,但是当我调用 API 时,不同的 API 端点上有一个授权标记,我得到了未授权,希望当然可以理解。
这引出了我的下一个问题。首先,我可能没有任何东西可以处理我的 Web API 中的授权,以及如何让我的 API 授权来自我的 AngularJS SPA 的调用,当它的端点正在被调用或请求。
下一步是什么?我需要了解什么才能理解和实施正确的流程between/through 这两个应用程序。
______________________UPDATE____________________________
所以我走得更远了。但现在我得到了 401 未经授权,所以我的 Angular SPA 无法通过授权标签。我错过了什么吗?
Javascript app.js:
var app = angular.module('app', ['AdalAngular']);
app.config(['$httpProvider', 'adalAuthenticationServiceProvider', function ($httpProvider, adalProvider) { //$routeProvider,
$httpProvider.defaults.withCredentials = true;
var endpoints = {
"https://localhost:44376/": "http://oauthsolutionadtest.onmicrosoft.com/theapi"
};
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'oauthsolutionadtest.onmicrosoft.com',
clientId: 'CLIENT-ID',
endpoints: endpoints,
},
$httpProvider
);
}]);
var sampleController = app.controller("sampleController", ["$scope", "$http", "adalAuthenticationService", function ($scope, $http, adalService) {
$scope.login = login;
$scope.logout = logout;
$scope.onlyAdmin = onlyAdmin;
function login(){
adalService.login();
};
function logout(){
adalService.logOut();
};
function onlyAdmin() {
alert("INNE_1");
$http.get("https://localhost:44376/api/testmessage")
.success(
function (data, status, headers, config, response) {
alert("INNE_2");
$scope.admin = true;
console.log(data, status, headers, config, response);
}).error(
function (response) {
alert("INNE_3 " + response);
console.log(response);
}
)
}
}])
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>Sample SPA (AngularJs) And Azure AD</title>
<meta charset="utf-8" />
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="Content/toaster.css" rel="stylesheet" />
<link href="Content/loading-bar.min.css" rel="stylesheet" />
</head>
<body ng-controller="sampleController">
<!--<div data-ng-view=""></div>-->
<div>
<button ng-click="login()" ng-hide="userInfo.isAuthenticated">Login</button>
<button ng-click="logout()" ng-show="userInfo.isAuthenticated">Logout</button>
<button ng-click="onlyAdmin()">
Admin
</button>
{{admin}}
<pre>
{{userInfo}}
</pre>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.13/js/adal.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.13/js/adal-angular.min.js"></script>
<script type="text/javascript" src="App/app.js"></script>
</body>
</html>
WEBAPI控制器:
using System;
using System.Configuration;
using System.Linq;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.Cors;
namespace OAuthSolution.API.Controllers
{
public class ContactController : ApiController
{
[Route("api/testmessage")]
[HttpGet]
[EnableCors(origins: "https://localhost:44311", headers: "*", methods: "GET, POST, OPTIONS", SupportsCredentials =true)]
[Authorize]
public string testMessage()
{
return "You got the Test Message";
}
[Route("api/theGet")]
[HttpGet]
[EnableCors(origins: "https://localhost:44311", headers: "*", methods: "*", SupportsCredentials = true)]
[Authorize]
public IHttpActionResult Get()
{
var adminGroupId = ConfigurationManager.AppSettings["adminGroupId"];
Claim groupAdmin = ClaimsPrincipal.Current.Claims.FirstOrDefault(x => x.Type == "groups" && x.Value.Equals(adminGroupId, StringComparison.CurrentCultureIgnoreCase));
if(groupAdmin != null)
{
return Ok("Admin");
}
return Unauthorized();
}
}
}
网络API Startup.cs:
/////STARTUP.CS
using Microsoft.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Owin;
using Microsoft.Owin.Security.ActiveDirectory;
using System.Configuration;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
[assembly: OwinStartup(typeof(OAuthSolution.API.Startup))]
namespace OAuthSolution.API
{
public partial class Startup
{
public void Configuration (IAppBuilder app)
{
ConfigureAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
private void ConfigureAuth(IAppBuilder app)
{
var azureADBearerAuthOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
};
azureADBearerAuthOptions.TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
};
app.UseWindowsAzureActiveDirectoryBearerAuthentication(azureADBearerAuthOptions);
}
}
}
WebApiConfig.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;
namespace OAuthSolution.API
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Web.Config:
Header:
从jwt.io解密的令牌:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "Y4ueK2oaINQiQb5YEBSYVyDcpAU",
"kid": "Y4ueK2oaINQiQb5YEBSYVyDcpAU"
}
{
"aud": "http://oauthsolutionadtest.onmicrosoft.com/theapi",
"iss": "https://sts.windows.net/f2f535e0-294f-4704-befc-8ce754f10bd7/",
"iat": 1486134484,
"nbf": 1486134484,
"exp": 1486138384,
"acr": "1",
"amr": [
"pwd"
],
"appid": "a9d7f295-1c8e-43bc-9600-bdc0bff1d567",
"appidacr": "0",
"e_exp": 10800,
"family_name": "admin",
"given_name": "admin",
"groups": [
"f929d8fd-e361-473d-8325-6e8d1ccba5a0"
],
"ipaddr": "90.224.252.71",
"name": "admin",
"oid": "251df8ba-112b-4c06-af7e-4c0899f0118b",
"platf": "3",
"scp": "user_impersonation",
"sub": "Ih0hL_bmMPuMeYk3R_gEWZZmUteJfL0F1afFhiPYUFU",
"tid": "f2f535e0-294f-4704-befc-8ce754f10bd7",
"unique_name": "admin@OAuthSolutionADTest.onmicrosoft.com",
"upn": "admin@OAuthSolutionADTest.onmicrosoft.com",
"ver": "1.0"
}
我想我找到了解决问题的方法...
我不得不添加这一行:
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
这个命名空间:
using Microsoft.Owin.Security.OAuth;
(也使它起作用:Microsoft.Owin.Host.SystemWeb
)
到我的 WebApiConfig.cs 文件,在 Register 方法中。
现在我可以通过 CORS 调用我的 API。
希望这对其他人有帮助。
另外,感谢大家的帮助!
因此,我又一次不得不留下大量时间来研究安全性。 我非常想了解如何让我的 AngularJS SPA 能够通过安全的环境调用我的 API。
我很难掌握的是我认为的安全令牌的路径。
因此,在 Azure Active Directory 开发人员指南中的 Microsoft 指南之一的帮助下,我已经设法使用 OAuth2 保护我的 AngularJS SPA。
我现在可以登录并获得进入 SPA 的授权,但是当我调用 API 时,不同的 API 端点上有一个授权标记,我得到了未授权,希望当然可以理解。
这引出了我的下一个问题。首先,我可能没有任何东西可以处理我的 Web API 中的授权,以及如何让我的 API 授权来自我的 AngularJS SPA 的调用,当它的端点正在被调用或请求。
下一步是什么?我需要了解什么才能理解和实施正确的流程between/through 这两个应用程序。
______________________UPDATE____________________________
所以我走得更远了。但现在我得到了 401 未经授权,所以我的 Angular SPA 无法通过授权标签。我错过了什么吗?
Javascript app.js:
var app = angular.module('app', ['AdalAngular']);
app.config(['$httpProvider', 'adalAuthenticationServiceProvider', function ($httpProvider, adalProvider) { //$routeProvider,
$httpProvider.defaults.withCredentials = true;
var endpoints = {
"https://localhost:44376/": "http://oauthsolutionadtest.onmicrosoft.com/theapi"
};
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'oauthsolutionadtest.onmicrosoft.com',
clientId: 'CLIENT-ID',
endpoints: endpoints,
},
$httpProvider
);
}]);
var sampleController = app.controller("sampleController", ["$scope", "$http", "adalAuthenticationService", function ($scope, $http, adalService) {
$scope.login = login;
$scope.logout = logout;
$scope.onlyAdmin = onlyAdmin;
function login(){
adalService.login();
};
function logout(){
adalService.logOut();
};
function onlyAdmin() {
alert("INNE_1");
$http.get("https://localhost:44376/api/testmessage")
.success(
function (data, status, headers, config, response) {
alert("INNE_2");
$scope.admin = true;
console.log(data, status, headers, config, response);
}).error(
function (response) {
alert("INNE_3 " + response);
console.log(response);
}
)
}
}])
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>Sample SPA (AngularJs) And Azure AD</title>
<meta charset="utf-8" />
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="Content/toaster.css" rel="stylesheet" />
<link href="Content/loading-bar.min.css" rel="stylesheet" />
</head>
<body ng-controller="sampleController">
<!--<div data-ng-view=""></div>-->
<div>
<button ng-click="login()" ng-hide="userInfo.isAuthenticated">Login</button>
<button ng-click="logout()" ng-show="userInfo.isAuthenticated">Logout</button>
<button ng-click="onlyAdmin()">
Admin
</button>
{{admin}}
<pre>
{{userInfo}}
</pre>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.13/js/adal.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.13/js/adal-angular.min.js"></script>
<script type="text/javascript" src="App/app.js"></script>
</body>
</html>
WEBAPI控制器:
using System;
using System.Configuration;
using System.Linq;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.Cors;
namespace OAuthSolution.API.Controllers
{
public class ContactController : ApiController
{
[Route("api/testmessage")]
[HttpGet]
[EnableCors(origins: "https://localhost:44311", headers: "*", methods: "GET, POST, OPTIONS", SupportsCredentials =true)]
[Authorize]
public string testMessage()
{
return "You got the Test Message";
}
[Route("api/theGet")]
[HttpGet]
[EnableCors(origins: "https://localhost:44311", headers: "*", methods: "*", SupportsCredentials = true)]
[Authorize]
public IHttpActionResult Get()
{
var adminGroupId = ConfigurationManager.AppSettings["adminGroupId"];
Claim groupAdmin = ClaimsPrincipal.Current.Claims.FirstOrDefault(x => x.Type == "groups" && x.Value.Equals(adminGroupId, StringComparison.CurrentCultureIgnoreCase));
if(groupAdmin != null)
{
return Ok("Admin");
}
return Unauthorized();
}
}
}
网络API Startup.cs:
/////STARTUP.CS
using Microsoft.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Owin;
using Microsoft.Owin.Security.ActiveDirectory;
using System.Configuration;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
[assembly: OwinStartup(typeof(OAuthSolution.API.Startup))]
namespace OAuthSolution.API
{
public partial class Startup
{
public void Configuration (IAppBuilder app)
{
ConfigureAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
private void ConfigureAuth(IAppBuilder app)
{
var azureADBearerAuthOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
};
azureADBearerAuthOptions.TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
};
app.UseWindowsAzureActiveDirectoryBearerAuthentication(azureADBearerAuthOptions);
}
}
}
WebApiConfig.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;
namespace OAuthSolution.API
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Web.Config:
Header:
从jwt.io解密的令牌:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "Y4ueK2oaINQiQb5YEBSYVyDcpAU",
"kid": "Y4ueK2oaINQiQb5YEBSYVyDcpAU"
}
{
"aud": "http://oauthsolutionadtest.onmicrosoft.com/theapi",
"iss": "https://sts.windows.net/f2f535e0-294f-4704-befc-8ce754f10bd7/",
"iat": 1486134484,
"nbf": 1486134484,
"exp": 1486138384,
"acr": "1",
"amr": [
"pwd"
],
"appid": "a9d7f295-1c8e-43bc-9600-bdc0bff1d567",
"appidacr": "0",
"e_exp": 10800,
"family_name": "admin",
"given_name": "admin",
"groups": [
"f929d8fd-e361-473d-8325-6e8d1ccba5a0"
],
"ipaddr": "90.224.252.71",
"name": "admin",
"oid": "251df8ba-112b-4c06-af7e-4c0899f0118b",
"platf": "3",
"scp": "user_impersonation",
"sub": "Ih0hL_bmMPuMeYk3R_gEWZZmUteJfL0F1afFhiPYUFU",
"tid": "f2f535e0-294f-4704-befc-8ce754f10bd7",
"unique_name": "admin@OAuthSolutionADTest.onmicrosoft.com",
"upn": "admin@OAuthSolutionADTest.onmicrosoft.com",
"ver": "1.0"
}
我想我找到了解决问题的方法...
我不得不添加这一行:
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
这个命名空间:
using Microsoft.Owin.Security.OAuth;
(也使它起作用:Microsoft.Owin.Host.SystemWeb
)
到我的 WebApiConfig.cs 文件,在 Register 方法中。
现在我可以通过 CORS 调用我的 API。
希望这对其他人有帮助。
另外,感谢大家的帮助!