回答:对于任何寻求此答案的人,我都可以通过在MSAL acquisitionToken调用范围内指定Web API来获得所需的令牌,如下所示:
let token = msal.acquireToken({
scopes: [ 'myFunctionApp.azurewebsites.net/user_impersonation' ]
})
完成此操作后,我将令牌用作Authentication标头中的Bearer令牌。除了调用MS Graph端点之外,我还可以使用它。我在一个安静的地方找到了此信息:
非常感谢@StanleyGong的帮助,最终导致了答案。
/////
过去几天,我一直在寻找如何有效保护从调用Azure功能应用程序的Azure Web应用程序提供的Vue SPA的安全。我已经为Web应用程序和功能应用程序打开了Easy Auth,并且正在调用/.auth/me
端点以获取ID令牌,我已将其读取为承载令牌。因此,我正在做的是调用/.auth/me
并使用返回的id_token
创建Authorization标头,但是调用函数app时仍然得到401 Unauthorized
。
代码从/.auth/me获取id_token并将其作为默认标头添加到所有Axios调用中(我确实认识到这需要刷新...我将在获得后创建所有逻辑一次通话有效):
let authUrl = '/.auth/me';
let response = await axios.get(authUrl);
let token = response.data[0].id_token;
axios.defaults.headers.common['Authorization'] = "Bearer " + token;
我可以看到请求中的Authorization标头中使用了令牌,该令牌紧随上述部分之后:
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Bearer eyJ0eXAiO...
我看到了这篇文章,并尝试使用其中的一些信息,包括克里斯·吉伦(Chris Gillum)的博客文章(虽然很有帮助,但仍然没有让我到达那里):Authentication for Azure Functions
关于如何使它工作的任何建议?我觉得我已经接近了,但我还没到那儿。如果这不是正确的解决方法,那么任何建议也将有所帮助。
我通常对身份缺乏经验,因此我一直在绕过术语,而文档的不一致对此没有帮助。
此外,有什么方法可以测试这些东西而无需在每次更改时都部署代码?最好通过某种方式从商店中获取令牌来进行测试,而无需将代码存储在Web应用程序服务器上……我想,但我只是想知道。
编辑:我刚刚意识到,我读过的所有帖子都建议从/.auth/me
返回访问令牌,但我没有得到。返回的JSON看起来像这样,就这样:
id_token: "eyJ0eXA...7_A"
provider_name: "aad"
user_claims: [{typ: "aud", val: "2...fa"},…]
user_id: "<<my email address>>"
另一个编辑:我发现我可以使用MSAL获得令牌,但其中包含的信息与/.auth/me
略有不同。使用任一令牌作为承载令牌仍会产生401。我确实注意到,在应用程序的AAD身份验证设置中,发行者URL不同。一个是sts.windows.net,另一个是login.windows.net。他们俩都拥有房客ID。不知道这是否有所作为,但是我尝试将它们设置为相同的值,但这没有帮助。
/.auth/me
令牌(当然,已清除):
{
"aud": "2fe...fa", (AAD app id)
"iss": "https://sts.windows.net/<< AD tenant id >>/",
"iat": 15785xxx,
"nbf": 15785xxx,
"exp": 15785xxx,
"aio": "AVQAq/...UQ=",
"amr": [
"pwd",
"mfa"
],
"family_name": "<< my last name >>",
"given_name": "<< my first name >>",
"ipaddr": "<< my ip >>",
"name": "<< my full name >>",
"nonce": "e32a...48",
"oid": "a0...0e",
"sub": "LNu...8l8",
"tid": "f14...2ca",
"unique_name": "<< my email >>",
"upn": "<< my email >>",
"uti": "i9O...TAQ",
"ver": "1.0"
}
MSAL访问令牌:
{
"aud": "000...000", (mostly 0s...not sure what this id is)
"iss": "https://sts.windows.net/<< AD tenant id >>",
"iat": 15785xxx,
"nbf": 15785xxx,
"exp": 15785xxx,
"acct": 0,
"acr": "1",
"aio": "AVQAq/8O...ZZ12s=", (different than above)
"amr": [
"pwd",
"mfa"
],
"app_displayname": "<< app name in AAD app registration >>",
"appid": "<< app GUID from AAD >>",
"appidacr": "0",
"family_name": "<< my last name >>",
"given_name": "<< my first name >>",
"ipaddr": "<< my ip >>",
"name": "<< my full name >>",
"oid": "a0...0e", (same as above)
"platf": "3",
"puid": "10...1B",
"scp": "User.Read profile openid email",
"signin_state": [
"kmsi"
],
"sub": "WuX...L3A",
"tid": "f14...2ca", (tenant id, same as above)
"unique_name": "<< my email >>",
"upn": "<< my email >>",
"uti": "UD...AA",
"ver": "1.0",
"xms_st": {
"sub": "LNu...8l8"
},
"xms_tcdt": 14...37
}
答案 0 :(得分:3)
对于您的方案,您可以在租户中将Azure AD本机应用程序注册为客户端,以获取access_token作为Bearer令牌来调用Azure函数。如果您使用的是服务到服务的呼叫,请参阅my previous post here。
如果您要登录用户,则也应该使用其他配置在租户中注册一个Azure AD应用程序: 向此应用程序添加user_impersonation权限,以便用户可以登录您的应用程序并调用您的Azure函数(请在此处注意您的Azure函数应用程序ID,稍后我们将使用它): 添加此权限并授予它:
完成这些步骤后,新应用程序将能够登录用户以调用您的Azure函数。
我不确定您的VUE应用程序代码是什么样的,但这是VUE adal sample,我的演示将以此为基础。
1.下载代码,然后转到src/main.js
,将其内容替换为以下代码:
import Vue from 'vue'
import axios from 'axios'
import { default as Adal, AxiosAuthHttp } from 'vue-adal'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
const functionBase = `<your Azure function URL>`
const functionResource = '<your Azure function application ID>'
Vue.use(Adal, {
config: {
tenant: '<your tenant ID>',
clientId: '<your new resistered app ID>',
redirectUri: '<redirect url you mapped in your new resgistered app ID, in this case it should be : http://localhost:8080>',
cacheLocation: 'localStorage'
},
requireAuthOnInitialize: true,
router: router
})
Vue.use({
install (vue, opts = {}) {
// Configures an axios http client with a interceptor to auto-acquire tokens
vue.prototype.$functionApi = AxiosAuthHttp.createNewClient({
// Required Params
axios: axios,
resourceId: functionResource, // Resource id to get a token against
// Optional Params
router: router, // Enables a router hook to auto-acquire a token for the specific resource
baseUrl: functionBase, // Base url to configure the client with
onTokenSuccess (http, context, token) { // Token success hook
// When an attempt to retrieve a token is successful, this will get called.
// This enables modification of the client after a successful call.
if (context.user) {
// Setup the client to talk with the Microsoft Graph API
http.defaults.baseURL = `${functionBase}`
console.log(token)
}
},
onTokenFailure (error) { // Token failure hook
// When an attempt to retrieve a token is not successful, this will get called.
console.log(error)
}
})
}
})
new Vue({
router,
render: h => h(App)
}).$mount('#app')
2。
转到src/views/Home.vue
,用以下代码替换<script>
部分的内容:
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'home',
components: {
HelloWorld
},
data () {
return {
msg: "Signing in..."
}
},
async created () {
if (this.$adal.isAuthenticated()) {
this.msg = "Hello, " + this.$adal.user.profile.name
let functionInfo = await this.getAzureFunctionInfo()
this.msg += " | function result : " + functionInfo
} else {
this.msg = "Please sign in"
}
},
methods: {
async getAzureFunctionInfo () {
let res = await this.$functionApi.get('',{
params: {
'name': 'test'
}
})
console.log(res)
return res.data
}
}
}
</script>
让我们测试结果: 由于此项目将在本地运行,因此您应该转到Azure功能=>平台功能=>所有设置以启用所有cors请求,以便可以从静态vue项目在本地测试功能:
我的函数逻辑很简单,如果用param调用它,它将回复一个hello响应:
运行项目,然后在私有浏览器窗口中通过url打开它:http://localhost:8080
将要求您登录,您会看到它可以成功调用Azure函数:
我认为这是您正在寻找的答案。
更新:
根据您的代码,您正在使用Azure AD V2登录用户Pls:
1)按照第二种解决方案重新启动Azure广告应用并完成权限授予过程,以便它可以登录用户并访问您的Azure功能。
2)在您的Azure AD中,通过名称(代表我的Azure函数名称为:stanfuntest)找到代表您的Azure函数应用的Azure AD应用: 在此处复制范围:
2)在您的VUE代码中,使用此应用程序ID作为客户端ID登录用户,修改代码以获取具有您刚刚找到的范围的访问令牌:
let token = msal.acquireToken( { scopes: [ 'https://stanfuntest.azurewebsites.net/user_impersonation' ] } )
希望有帮助。