做了两个例子:express 和 eggjs,详情如下:
先决条件
- Nodejs
- VS Code 或其他代码编辑器
注册应用程序
首先,请完成向 Microsoft 标识平台注册应用程序中的步骤来注册你的应用。
对于应用注册,请使用以下设置:
- 名称:ExpressWebApp(建议)
- 支持的帐户类型:任何组织目录中的帐户(任何 Azure AD 目录 - 多租户)和个人 Microsoft 帐户(例如 Skype、Xbox)
- 平台类型:Web
- 重定向 URI:http://localhost:3000/redirect
- 客户端机密:*********(记录此值以便在后面的步骤中使用 - 它只显示一次)
express环境
const msal = require('@azure/msal-node');
const express = require("express");
const config = {
auth: {
clientId: "******",
authority: "********",
clientSecret: "********"
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
const cca = new msal.ConfidentialClientApplication(config);
const SERVER_PORT = process.env.PORT || 3001;
const app = express();
// redirectUri:接口2 redirect地址 http://localhost:3000/redirect
let redirectUri = 'http://localhost:3001/redirect'
app.get('/', (req, res) => {
const authCodeUrlParameters = {
scopes: ["user.read"],
redirectUri: redirectUri, //接口2 redirect地址
abc: '123asdqwe'
};
cca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
// response 为微软登陆链接,前端或后端重定向到response
res.redirect(response);
}).catch((error) => console.log(JSON.stringify(error)));
});
app.get('/redirect', (req, res) => {
const tokenRequest = {
code: req.query.code, // 参数code
scopes: ["user.read"],
redirectUri: redirectUri, // 接口2 redirect地址
};
cca.acquireTokenByCode(tokenRequest).then((response) => {
// response为个人基本信息,可做token操作
console.log("\nResponse: \n:", response);
res.sendStatus(200);
}).catch((error) => {
console.log(error);
res.status(500).send(error);
});
});
app.listen(SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port ${SERVER_PORT}!`))
复制代码
eggjs环境
// controller/user.js
// jumpRedirect: 跳转链接
// msalRedirect: http://localhost:3000/redirect
const Controller = require('../core/baseController');
const msal = require('@azure/msal-node');
const config = {
auth: {
clientId: "******",
authority: "******",
clientSecret: "******"
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
// console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
const cca = new msal.ConfidentialClientApplication(config);
class UserController extends Controller {
async login() {
const { ctx } = this
const authCodeUrlParameters = {
scopes: ["user.read"],
redirectUri: this.config.msalRedirect,
};
// get url to sign user in and consent to scopes needed for application
let data = await new Promise((resolve, reject) => {
cca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
resolve(response)
}).catch((error) => console.log(JSON.stringify(error)));
})
this.success({data})
}
async redirect() {
const { ctx } = this
const tokenRequest = {
code: ctx.query.code,
scopes: ["user.read"],
redirectUri: this.config.msalRedirect,
};
let data = await new Promise((resolve, reject) => {
cca.acquireTokenByCode(tokenRequest).then((response) => {
// console.log("\nResponse: \n:", response);
resolve(response)
}).catch((error) => {
console.log(error);
});
})
ctx.redirect(`${this.config.jumpRedirect}`);
}
}
module.exports = UserController;
复制代码
优化
重定向地址为前端页面地址,前端把微软传回来的code给后端,并请求后端接口获取用户信息
前端需要做的
login.vue
<el-link :href="thirdMicrosoft" :underline="false">
Microsoft Azure
</el-link>
const state = reactive({
thirdMicrosoft: import.meta.env.VITE_MICROSOFT_AZURE
});
.env
VITE_MICROSOFT_AZURE = `https://login.microsoftonline.com/${'authority code'}/oauth2/v2.0/authorize?client_id=${client_id}&response_type=code&redirect_uri=${'前端looading页地址'/azure}t&response_mode=query&scope=offline_access%20user.read%20mail.read&state=12345`
azure.vue
<template>
<div></div>
</template>
onMounted(async () => {
let { code } = route.query
if (code) {
let res = await loginByMicrosoft({code})
let { userInfo, token} = res.data
} else {
ElMessage({
type: 'error',
message: '登录参数错误',
duration: 3000,
onClose: () => {
router.push({ path: '/login' })
}
})
}
})
复制代码
后端需要做的
参考上文后端代码