Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 61 additions & 20 deletions docs/site/tutorials/authentication/Authentication-Tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,12 @@ application, follow these steps:
1. In the `UserController` section, click on `POST /users`, click on
`'Try it out'`, specify:

```ts
```json
{
"id": "1",
"email": "user1@example.com",
"password": "thel0ngp@55w0rd",
"firstName": "User",
"lastName": "One"
"email": "user1@example.com",
"password": "thel0ngp@55w0rd",
"firstName": "User",
"lastName": "One"
}
```

Expand All @@ -101,9 +100,9 @@ application, follow these steps:
1. In the `UserController` section, click on `POST /users/login`, click on
`'Try it out'`, specify:

```ts
```json
{
"email": "user1@example.com",
"email": "user1@example.com",
"password": "thel0ngp@55w0rd"
}
```
Expand All @@ -114,7 +113,7 @@ application, follow these steps:

For example:

```ts
```json
{
"token": "some.token.value"
}
Expand Down Expand Up @@ -161,10 +160,11 @@ application, follow these steps:
[HTTP 401 UnAuthorized](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401)
is thrown.

The response is:
The response contains a unique value in the `id` field (generated by the
database) and `name` field with the full user name:

```sh
{"id":"1","name":"User One"}
```json
{"id": "5dd6acee242760334f6aef65", "name": "User One"}
```

## Adding JWT Authentication to a LoopBack 4 Application
Expand Down Expand Up @@ -193,9 +193,7 @@ so it is important to add the component in the `ShoppingApplication` class in
[loopback4-example-shopping/packages/shopping/src/application.ts](https://github.com/strongloop/loopback4-example-shopping/blob/master/packages/shopping/src/application.ts).

```ts
import {
AuthenticationComponent
} from '@loopback/authentication';
import {AuthenticationComponent} from '@loopback/authentication';

export class ShoppingApplication extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
Expand All @@ -209,6 +207,9 @@ export class ShoppingApplication extends BootMixin(
this.component(AuthenticationComponent);

// ...
}
// ...
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this change, GitHub's syntax highlighter was confused - notice the text in "Securing and Enpoint..." is rendered in blue:

Screen Shot 2019-11-25 at 09 36 02

Also Prettier was not able to automatically format the code. Once I added closing curly braces, Prettier shortened the import line and GitHub started to render the text in the next section as regular text (in black color) again.

```

### Securing an Endpoint with the Authentication Decorator
Expand Down Expand Up @@ -768,6 +769,27 @@ In the `UserController` class in the
users can be added by performing a `POST` request to the `/users` endpoint which
is handled by the `create()` function.

Because user credentials like password are stored outside of the main user
profile, we need to create a new model (a
[Data Transfer Object](https://en.wikipedia.org/wiki/Data_transfer_object)) to
describe data required to create a new user. The class inherits from `User`
model to include all user profile properties, and adds a new property `password`
allowing clients to specify the password too.

```ts
@model()
export class NewUserRequest extends User {
@property({
type: 'string',
required: true,
})
password: string;
}
```

The controller method `UserController.create` then has to remove additional
properties like `password` before passing the data to Repository (and database).

```ts
export class UserController {
constructor(
Expand All @@ -784,16 +806,35 @@ export class UserController {
// ...

@post('/users')
async create(@requestBody() user: User): Promise<User> {
async create(
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(NewUserRequest, {
title: 'NewUser',
}),
},
},
})
newUserRequest: NewUserRequest,
): Promise<User> {
// ensure a valid email value and password value
validateCredentials(_.pick(user, ['email', 'password']));
validateCredentials(_.pick(newUserRequest, ['email', 'password']));

// encrypt the password
user.password = await this.passwordHasher.hashPassword(user.password);
const password = await this.passwordHasher.hashPassword(
newUserRequest.password,
);

// create the new user
const savedUser = await this.userRepository.create(user);
delete savedUser.password;
const savedUser = await this.userRepository.create(
_.omit(newUserRequest, 'password'),
);

// set the password
await this.userRepository
.userCredentials(savedUser.id)
.create({password});

return savedUser;
}
Expand Down