I've been working with Loopback 4. I'm facing an error recently. After authentication is successful and I try to access the current user from my end point. I get this error
13:31:07 0|index | Unhandled error in POST /posts: 500 Error: The key 'authentication.currentUser' is not bound to any value in context application
13:31:07 0|index | at HomeApplication.getBinding (/Development/home/node_modules/@loopback/context/dist/context.js:596:15)
13:31:07 0|index | at RestServer.getBinding (/Development/home/node_modules/@loopback/context/dist/context.js:592:33)
13:31:07 0|index | at RequestContext.getBinding (/Development/home/node_modules/@loopback/context/dist/context.js:592:33)
13:31:07 0|index | at RequestContext.getValueOrPromise (/Development/home/node_modules/@loopback/context/dist/context.js:651:30)
13:31:07 0|index | at RequestContext.get (/Development/home/node_modules/@loopback/context/dist/context.js:574:21)
13:31:07 0|index | at PostController.getter [as getCurrentUser] (/Development/home/node_modules/@loopback/context/dist/inject.js:258:20)
13:31:07 0|index | at PostController.<anonymous> (/Development/home/dist/controllers/user/post.controller.js:57:35)
I've tried all the available solutions to this problem on GitHub and StackOverflow. Been searching for a solution for a couple of days now.
I also tried to debug this myself by putting console logs in generated files. This is what I did in auth-action.provider.js
async action(request) {
const strategy = await this.getStrategy();
if (!strategy) {
// The invoked operation does not require authentication.
return undefined;
}
console.log(`Strategy obtained successfully`)
const userProfile = await strategy.authenticate(request);
if (!userProfile) {
// important to throw a non-protocol-specific error here
const error = new Error(`User profile not returned from strategy's authenticate function`);
Object.assign(error, {
code: types_1.USER_PROFILE_NOT_FOUND,
});
throw error;
}
console.log(`User obtained successfully`)
console.log(JSON.stringify(userProfile))
this.setCurrentUser(userProfile);
console.log(`Called setCurrentUser`)
return userProfile;
}
result after this
13:46:55 0|index | Authenticating
13:46:55 0|index | Strategy obtained successfully
13:46:55 0|index | ~~ Authenticating: token --> 9823eb1940eae6df49c54698d8a71b319f0b00635321a02632965a7667d69ce68883b61d803f0691c2b393bc9841606b153fa28fc853ecfd41bd647725479b54, mode --> personal~~
13:46:55 0|index | User found. Id --> 5d8f549de7179a022443e34e
13:46:55 0|index | User obtained successfully
13:46:55 0|index | {"email":"[email protected]","id":"5d8f549de7179a022443e34e","name":"name","image":null,"designation":"Designation","company":"string"}
13:46:55 0|index | Called setCurrentUser
13:46:55 0|index | Trace: Error: The key 'authentication.currentUser' is not bound to any value in context application
13:46:55 0|index | at HomeApplication.getBinding (/Development/home/node_modules/@loopback/context/dist/context.js:596:15)
13:46:55 0|index | at RestServer.getBinding (/Development/home/node_modules/@loopback/context/dist/context.js:592:33)
13:46:55 0|index | at RequestContext.getBinding (/Development/home/node_modules/@loopback/context/dist/context.js:592:33)
13:46:55 0|index | at RequestContext.getValueOrPromise (/Development/home/node_modules/@loopback/context/dist/context.js:651:30)
13:46:55 0|index | at RequestContext.get (/Development/home/node_modules/@loopback/context/dist/context.js:574:21)
13:46:55 0|index | at PostController.getter [as getCurrentUser] (/Development/home/node_modules/@loopback/context/dist/inject.js:258:20)
13:46:55 0|index | at PostController.<anonymous> (/Development/home/dist/controllers/user/post.controller.js:57:35)
As you can see everything is working as expected. It's just that when I try to get the user in my controller, this error occurs. If I don't try to access the user, everything works fine.
My guess is something is wrong with the setCurrentUser method injected in auth-action.provider.
Here is my controller if you need it.
export class PostController {
static MAX_POST_LENGTH = 800;
constructor(
@repository(PostRepository)
public postRepository: PostRepository,
@inject(MyAuthBindings.USER_TOKEN_SERVICE)
public userTokenService: UserTokenService,
@inject.getter(AuthenticationBindings.CURRENT_USER)
public getCurrentUser: Getter<MyUserProfile>,
) {
}
@post('/posts', {
responses: {
'200': {
description: 'Post model instance',
content: {'application/json': {schema: {'x-ts-type': UserPost}}},
},
},
})
@authenticate('user')
async create(
@param.header.string('token') token: string,
@param.header.string('mode') mode: string,
@requestBody() newPostRequest: PostRequest): Promise<UserPost> {
if (newPostRequest.body.length > PostController.MAX_POST_LENGTH) {
throw new HttpErrors.BadRequest(`Post body cannot be larger than ${PostController.MAX_POST_LENGTH} characters`);
}
let user = await this.getCurrentUser();
console.log(`Authenticated user --> ${JSON.stringify(user, null, 2)}`);
let postItem = new Post(newPostRequest);
postItem.userId = user.id;
postItem.createdAt = new Date();
postItem.updatedAt = new Date();
postItem = await this.postRepository.create(postItem);
if (postItem.id != null)
PostController.checkAndSendStyleworkPostNotification(user.id, postItem.id);
return new UserPost(postItem, user, user);
}
Processing does not get to the log in the method above.
P.S. This problem started to occur after @loopback/authentication update from 2.2.2 to 3.0.0
I fixed the issue. The problem was as noted in Authentication component documentation that AuthenticationBindings.CURRENT_USER is now an alias of SecurityBindings.USER in @loopback/security.
I just had to replace AuthenticationBindings.CURRENT_USER with SecurityBindings.USER. This change was made in v3.0.0 as I noted in my question.