我正在开发一个用户使用 MSAL 身份验证登录的应用程序,并且在注册过程中,我已授予 Microsoft Graph API 的
user.ReadBasic.All
权限范围。现在,我需要验证提供的用户电子邮件(登录用户和登录用户提供的用于验证的电子邮件不同)是否属于同一租户,如果验证通过,则检索他们的全名。
这是我目前的方法:
但是,这种方法仅验证电子邮件域是否与租户匹配,这并不能保证电子邮件属于实际用户。相反,我需要确保电子邮件属于租户内的有效用户并检索他们的全名。
任何人都可以指导我如何实现这一目标吗?具体来说,如何使用 MSAL 身份验证和 Azure Functions 验证用户的电子邮件并检索其全名?
以下是我的代码,其中我删除了比较和 jwt 解码逻辑。
module.exports = async function (context, req) {
const tenantId = "YOUR_TENANT_ID";
if (req.method === 'POST') {
try {
const { email } = req.body;
const token = req.headers.authorization;
if (!token || !email) {
context.res = {
status: 400,
body: "Token in the 'Authorization' header and email in the request body are required."
};
return;
}
const bearerToken = token.split(' ')[1];
// we decode jwt token to get tenantid and email
if (!decoded || decoded.tid !== tenantId) {
context.res = {
status: 403,
body: JSON.stringify({ error: 'Unauthorized: Invalid token or tenant' })
};
return;
}
const userEmail = decoded.preferred_username;
if (typeof userEmail !== 'string' || typeof email !== 'string') {
context.res = {
status: 400,
body: JSON.stringify({ error: 'Invalid email format' })
};
return;
}
// we check email domain comparison here
if (providedDomain !== tokenDomain) {
context.res = {
status: 400,
body: JSON.stringify({ error: 'Email does not match the tenant. Verification failed.' })
};
return;
}
context.res = {
status: 200,
body: JSON.stringify({ message: 'Email matches the tenant. Verification successful.' })
};
} catch (error) {
context.log.error('Token verification error:', error.message);
context.res = {
status: 401,
body: JSON.stringify({ error: 'Invalid token' })
};
}
} else {
context.res = {
status: 405,
body: "Method Not Allowed"
};
}
};
任何帮助或建议将不胜感激。谢谢!
我想做的就是创建一个 Azure 函数 API,当来自同一租户的登录用户发送验证其他电子邮件的请求时,该 API 会检查电子邮件是否有效(以便用户可以排除任何类型的未验证电子邮件)公司内部注册)。
您需要向Graph API发出请求来检索用户的基本资料。您需要比较的字段是
mail
。
如果解码令牌中的电子邮件地址是用户的电子邮件别名,并且您希望允许使用电子邮件别名,则需要
User.Read.All
权限。这将允许您检索 full 配置文件,其中包含 proxyAddresses
数组。您需要从返回值的开头删除“SMTP:”部分,或者将“SMTP:”添加到比较中令牌的电子邮件开头。
这里有一些用于检索用户个人资料的代码:
const msal = require('@azure/msal-node');
const https = require('https');
// MSAL configuration
const msalConfig = {
auth: {
clientId: 'your_client_id',
authority: 'https://login.microsoftonline.com/your_tenant_id',
clientSecret: 'your_client_secret'
}
};
const cca = new msal.ConfidentialClientApplication(msalConfig);
module.exports = async function (context, req) {
const userEmail = req.query.email; // Get user's email address from request query
if (!userEmail) {
context.res = {
status: 400,
body: 'User email address is required'
};
return;
}
// Acquire a token for the Microsoft Graph API
const tokenRequest = {
scopes: ['https://graph.microsoft.com/.default']
};
try {
const tokenResponse = await cca.acquireTokenByClientCredential(tokenRequest);
// Microsoft Graph API endpoint for specific user profile
const graphApiEndpoint = `https://graph.microsoft.com/v1.0/users/${userEmail}`;
const options = {
hostname: 'graph.microsoft.com',
path: `/v1.0/users/${userEmail}`,
method: 'GET',
headers: {
'Authorization': `Bearer ${tokenResponse.accessToken}`
}
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
const userProfile = JSON.parse(data);
context.res = {
body: {
id: userProfile.id,
displayName: userProfile.displayName,
givenName: userProfile.givenName,
surname: userProfile.surname,
mail: userProfile.mail
}
};
});
});
req.on('error', (error) => {
context.res = {
status: 500,
body: error.message
};
});
req.end();
} catch (error) {
context.res = {
status: error.response ? error.response.status : 500,
body: error.response ? error.response.data : 'Internal Server Error'
};
}
};