【发布时间】:2018-06-21 02:05:30
【问题描述】:
我有一个用 ReactJS 编写的单页应用程序 (SPA)。我正在尝试查询 Graph API。我正在使用 msal.js 库来处理我的身份验证。我正在使用 Azure AD B2C 来管理我的帐户。到目前为止我所拥有的:
我可以登录 Google 并将我的个人资料信息返回到我的 SPA。但是,当请求 accessToken 时,结果为空。我很肯定我做错了什么,我猜它是围绕我的应用程序注册和范围。当我注册我的应用程序时,它有一个名为“user_impersonation”的默认范围。当我输入这个时,我意识到我注册了我的客户端(SPA)而不是 API。两个都需要注册吗?我不确定如何注册 Graph。
我的代码:
App.js
import AuthService from '../services/auth.service';
import GraphService from '../services/graph.service';
class App extends Component {
constructor() {
super();
this.authService = new AuthService();
this.graphService = new GraphService();
this.state = {
user: null,
userInfo: null,
apiCallFailed: false,
loginFailed: false
};
}
componentWillMount() {}
callAPI = () => {
this.setState({
apiCallFailed: false
});
this.authService.getToken().then(
token => {
this.graphService.getUserInfo(token).then(
data => {
this.setState({
userInfo: data
});
},
error => {
console.error(error);
this.setState({
apiCallFailed: true
});
}
);
},
error => {
console.error(error);
this.setState({
apiCallFailed: true
});
}
);
};
logout = () => {
this.authService.logout();
};
login = () => {
this.setState({
loginFailed: false
});
this.authService.login().then(
user => {
if (user) {
this.setState({
user: user
});
} else {
this.setState({
loginFailed: true
});
}
},
() => {
this.setState({
loginFailed: true
});
}
);
};
render() {
let templates = [];
if (this.state.user) {
templates.push(
<div key="loggedIn">
<button onClick={this.callAPI} type="button">
Call Graph's /me API
</button>
<button onClick={this.logout} type="button">
Logout
</button>
<h3>Hello {this.state.user.name}</h3>
</div>
);
} else {
templates.push(
<div key="loggedIn">
<button onClick={this.login} type="button">
Login with Google
</button>
</div>
);
}
if (this.state.userInfo) {
templates.push(
<pre key="userInfo">{JSON.stringify(this.state.userInfo, null, 4)}</pre>
);
}
if (this.state.loginFailed) {
templates.push(<strong key="loginFailed">Login unsuccessful</strong>);
}
if (this.state.apiCallFailed) {
templates.push(
<strong key="apiCallFailed">Graph API call unsuccessful</strong>
);
}
return (
<div className="App">
<Header />
<Main />
{templates}
</div>
);
}
}
export default App
auth.service.js:
import * as Msal from 'msal';
export default class AuthService {
constructor() {
// let PROD_REDIRECT_URI = 'https://sunilbandla.github.io/react-msal-sample/';
// let redirectUri = window.location.origin;
// let redirectUri = 'http://localhost:3000/auth/openid/return'
// if (window.location.hostname !== '127.0.0.1') {
// redirectUri = PROD_REDIRECT_URI;
// }
this.applicationConfig = {
clientID: 'my_client_id',
authority: "https://login.microsoftonline.com/tfp/my_app_name.onmicrosoft.com/b2c_1_google-sisu",
b2cScopes: ['https://my_app_name.onmicrosoft.com/my_api_name/user_impersonation email openid profile']
// b2cScopes: ['graph.microsoft.com user.read']
};
this.app = new Msal.UserAgentApplication(this.applicationConfig.clientID, this.applicationConfig.authority, function (errorDesc, token, error, tokenType) {});
// this.logger = new Msal.logger(loggerCallback, { level: Msal.LogLevel.Verbose, correlationId:'12345' });
}
login = () => {
return this.app.loginPopup(this.applicationConfig.b2cScopes).then(
idToken => {
const user = this.app.getUser();
if (user) {
return user;
} else {
return null;
}
},
() => {
return null;
}
);
};
logout = () => {
this.app.logout();
};
getToken = () => {
return this.app.acquireTokenSilent(this.applicationConfig.b2cScopes).then(
accessToken => {
return accessToken;
},
error => {
return this.app
.acquireTokenPopup(this.applicationConfig.b2cScopes)
.then(
accessToken => {
return accessToken;
},
err => {
console.error(err);
}
);
}
);
};
}
graph.service.js
export default class GraphService {
constructor() {
// this.graphUrl = 'https://graph.microsoft.com/v1.0';
this.graphUrl = 'http://httpbin.org/headers';
}
getUserInfo = token => {
const headers = new Headers({ Authorization: `Bearer ${token}` });
const options = {
headers
};
return fetch(`${this.graphUrl}`, options)
.then(response => response.json())
.catch(response => {
throw new Error(response.text());
});
};
}
我在尝试查询 Graph API 时遇到拒绝访问错误,因此我将 graph.microsoft.com/1.0 替换为 httpbin,这样我实际上可以看到传入的内容。这是我看到令牌为空的地方.这是我从 Microsoft 的示例项目中提取的完全相同的代码,当我使用他们的代码时它可以工作。他们没有显示的是如何配置 AAD B2C 和应用程序注册,这是我认为我的问题所在。
【问题讨论】:
-
发布您的代码!尤其是您如何尝试获取 access_token。
-
你能组织一个具体的问题吗?一开始你谈论 Azure 函数,最后你尝试调用 Microsoft Graph。两件事 - 首先,使用 Azure AD B2C 你不能使用 MS Graph。 B2C is not about MS Graph。第二 - 去阅读docs about WebAPIs and Scopes in B2C
-
这似乎表明您可以(并且应该)使用 Graph API:docs.microsoft.com/en-us/azure/active-directory-b2c/…
标签: reactjs azure azure-active-directory azure-ad-b2c msal