I am using TSED - TypeScript Express Decorators (https://tsed.io) and it replaces express code like:
server.get(\'/api/tasks\', passport.authenticate(\'oauth-
This is a solution to work around what I believe is a problem with passport-azure-ad
being async but with no way to control this. It is not the answer I'd like - to confirm what I've said or to deny what I've said and to provide a solution that works.
The following is a solution for the https://tsed.io framework. In https://github.com/TypedProject/ts-express-decorators/issues/559 they suggest not using @OverrideMiddleware(AuthenticatedMiddleware)
but to use a @UseAuth
middleware. It works so for illustration purposes that is not important here (I will work through the feedback shortly).
@OverrideMiddleware(AuthenticatedMiddleware)
export class UserAuthMiddleware implements IMiddleware {
constructor(@Inject() private authService: AuthService) {
}
// NO THIS VERSION DOES NOT WORK. I even removed checkForAuthentication() and
// inlined the setInterval() but it made no difference
// Before the 200 is sent WITH content, a 204 NO CONTENT is
// HAD TO CHANGE to the setTimeout() version
// async checkForAuthentication(request: express.Request): Promise {
// return new Promise(resolve => {
// let iterations = 30;
// const id = setInterval(() => {
// if (request.isAuthenticated() || iterations-- <= 0) {
// clearInterval(id);
// resolve();
// }
// }, 50);
// });
// }
// @async
public use(
@EndpointInfo() endpoint: EndpointMetadata,
@Request() request: express.Request,
@Response() response: express.Response,
@Next() next: express.NextFunction
) {
const options = endpoint.get(AuthenticatedMiddleware) || {};
this.authService.authenticate(request, response, next);
// AS DISCUSSED above this doesn't work
// await this.checkForAuthentication(request);
// TODO - check roles in options against AD scopes
// if (!request.isAuthenticated()) {
// throw new Forbidden('Forbidden');
// }
// next();
// HAD TO USE setTimeout()
setTimeout(() => {
if (!request.isAuthenticated()) {
console.log(`throw forbidden`);
throw new Forbidden('Forbidden');
}
next();
}, 1500);
}
Edit - I had a version that used setInterval()
but I found it didn't work. I even tried inlining the code in to the one method so I could remove the async
. It seemed to cause the @Post
the UserAuthMiddleware
is attached to, to complete immediately and return a 204 "No Content". The sequence would complete after this and a 200 with the desired content would be returned but it was too late. I don't understand why.