connect to story #2246
I picked the authentication-passport
module to start the spike for a more
flexible user profile because, compared with custom authentication strategies,
users have less control over the returned user when using the passport adapter.
I believe that if we could find a solution for the passport based strategies,
applying a similar approach to a custom strategy would be easy.
A converter function is passed into the StrategyAdapter
's constructor. It
takes in a custom user, converts it to a user profile described by
UserProfile
, and then returns it.
See the corresponding change made in file 'authentication-with-passport-strategy-adapter.acceptance.ts':
- Type
UserProfileInDB
is defined to describe the custom user. In a real application it should be a custom User model. - Define a factory function
userProfileFactory
that turns anUserProfileInDB
instance into a user profile. It's provided in the constructor when creating the adapter. - The converter is invoked in the strategy's
authentication()
function to make sure it returns a user profile of typeUserProfile
- If the strategy is returned in a provider, you can inject the factory.
- I added an example in the create passport based strategy with provider section.
I created a test case called "test user profile factory" to apply the user profile factory in a token based authentication. Here is the scenario:
-
The app has a user model called
MyUser
, which has- a property which is also defined in
UserProfile
in the same type. E.g. They both haveemail
as string. - a property which is also defined in
UserProfile
but in a different type. E.g.MyUser
hasid
as number whileUserProfile
has it as string. - a required property not defined in
UserProfile
- an optional property not defined in
UserProfile
- a property which is also defined in
-
There is a user profile factory called
MyUserProfileFactory
which:- picks a minimum set of identity properties from the found user
- converts a found user to a user profile. ((Those 4 properties in
MyUser
should cover all the possibilities in the conversion)
-
The factory function is injected in
MyUserController
:- Added a new key in
AuthenticationBindings
calledUSER_PROFILE_FACTORY
that can be used in injection.
- Added a new key in
-
When a user logs in, the controller function
login
calls the factory function to generate corresponding user profile, and uses it as the payload to generate the token. -
Requests with the token in header will have the correct user profile injected in the controller functions.
- Add interface
UserProfileFactory
and keyUSER_PROFILE_FACTORY
in@loopback/authentication
to help developers inject the factory wherever it's needed. - Add
userProfileFactory
inStrategyAdapter
's constructor. - Tests
- Document
A user profile related refactor in @loopback/authorization
: the
authorizeInterceptor
should use TypedPrincipal
instead of Principal
in the
authorization context. And we should provide a default factory that converts a
user profile to a typed principal in @loopback/security
. See PR
#3807