@@ -5,12 +5,14 @@ Interact with AWS Cognito from your Ember app.
5
5
This uses ` amazon-cognito-identity-js ` under the hood, which is considerably smaller in footprint than the quite enormous AWS Amplify SDK.
6
6
If all you need is a way to work with the JWT tokens priovded by Cognito, then this addon is perfect for you.
7
7
8
+ [ Upgrading from 3.x to 4.x] ( MIGRATION_v4.md )
9
+
8
10
## Compatibility
9
11
10
- * Ember.js v3.24 or above
11
- * Ember CLI v3.24 or above
12
- * Node.js v14 or above
13
- * Native promise support required
12
+ - Ember.js v3.24 or above
13
+ - Ember CLI v3.24 or above
14
+ - Node.js v14 or above
15
+ - Native promise support required
14
16
15
17
## Installation
16
18
@@ -59,66 +61,60 @@ export default class ApplicationRoute extends Route {
59
61
After logging in (see below) you can access the JTW token like this:
60
62
61
63
``` js
62
- let token = this .cognito .cognitoData .jwtToken ;
64
+ let token = this .cognito .session .jwtToken ;
63
65
```
64
66
65
67
Here is a summary of the most important available methods - all methods return a promise:
66
68
67
69
``` js
68
70
cognito .restoreAndLoad ();
69
71
cognito .authenticate ({ username, password });
70
- cognito .authenticateUser ({ username, password } );
72
+ cognito .mfaCompleteAuthentication (code );
71
73
cognito .logout ();
72
- cognito .invalidateAccessTokens ();
73
- cognito .triggerResetPasswordMail ({ username });
74
- cognito .updateResetPassword ({ username, code, newPassword });
75
- cognito .setNewPassword ({ username, password, newPassword });
76
- cognito .updatePassword ({ oldPassword, newPassword });
77
- cognito .updateAttributes (attributeMap);
74
+ cognito .invalidateAccessToken ();
75
+
76
+ cognito .user .updatePassword ();
77
+ cognito .user .updateAttributes ();
78
+
79
+ cognito .session .refresh ();
80
+ cognito .session .refreshIfNeeded ();
81
+ cognito .session .secondsUntilExpires ();
82
+
83
+ cognito .unauthenticated .verifyUserAuthentication ({ username, password });
84
+ cognito .unauthenticated .triggerResetPasswordMail ({ username });
85
+ cognito .unauthenticated .updateResetPassword ({ username, code, newPassword });
86
+ cognito .unauthenticated .setInitialPassword ({ username, password, newPassword });
78
87
```
79
88
80
89
## Cognito service
81
90
82
91
The ` cognito ` service provides promise-ified methods to work with AWS Cognito.
83
92
84
- ### isAuthenticated
85
-
86
- Will be true if a user is currently logged in.
87
- This means that you can safely access ` cognitoData ` and work with it.
93
+ ``` js
94
+ if (cognito .isAuthenticated ) {
95
+ let { user, session } = cognito;
88
96
89
- ### cognitoData
97
+ // See below for available properties & methods on user/session objects
98
+ } else {
99
+ let { unauthenticated } = cognito;
90
100
91
- This property will contain an object with your main Cognito-related information, if the user is logged in.
92
- If the user is not logged in, this will be ` null ` .
101
+ // See below for available properties on unauthenticated object
102
+ }
103
+ ```
93
104
94
- This is an object that looks like this:
105
+ ### ` isAuthenticated `
95
106
96
- ``` js
97
- let cognitoData = {
98
- cognitoUser: CognitoUser,
99
- cognitoUserSession: CognitoUserSession,
100
- jwtToken: ' xxxxx' ,
101
- userAttributes: { Email: ' ...' },
102
- getAccessToken : () => CognitoAccessToken,
103
- getIdToken : () => CognitoIdToken,
104
- mfa: {
105
- enable : () => {},
106
- disable : () => {},
107
- isEnabled : () => {},
108
- setupDevice : () => {},
109
- verifyDevice : (code ) => {},
110
- },
111
- };
112
- ```
107
+ Will be true if a user is currently logged in.
108
+ This means that you can safely access ` session ` and ` user ` and work with it.
113
109
114
- ### restoreAndLoad()
110
+ ### ` restoreAndLoad() `
115
111
116
112
Will try to lookup a prior session in local storage and authenticate the user.
117
113
118
114
If this resolves, you can assume that the user is logged in. It will reject if the user is not logged in.
119
115
Call this (and wait for it to complete) in your application route!
120
116
121
- ### authenticate({ username, password })
117
+ ### ` authenticate({ username, password }) `
122
118
123
119
Try to login with the given username & password.
124
120
Will reject with an Error, or resolve if successfull.
@@ -133,53 +129,149 @@ cognito: {
133
129
}
134
130
```
135
131
136
- ### authenticateUser({ username, password })
132
+ ### ` mfaCompleteAuthentication(code) `
137
133
138
- Verify only the given username & password.
139
- This will _ not_ sign the user in, but can be used to e.g. guard special places in your app behind a repeated password check.
140
- Will reject with an Error, or resolve if successfull.
134
+ This has to be called when ` authenticate() ` rejects with ` MfaCodeRequiredError ` .
141
135
142
- ### logout()
136
+ Returns a promise & signs the user in (if successful).
137
+
138
+ ### ` logout() `
143
139
144
140
Log out the user from the current device.
145
141
146
- ### invalidateAccessTokens()
142
+ ### ` invalidateAccessToken() `
147
143
148
- Logout & invalidate all issues access tokens (also on other devices).
144
+ Logout & invalidate all issued access tokens (also on other devices).
149
145
In contrast, ` logout() ` does not revoke access tokens, it only removes them locally.
150
146
151
147
Returns a promise.
152
148
153
- ### triggerResetPasswordMail({ username })
149
+ ## session
154
150
155
- Trigger an email to get a verification code to reset the password .
151
+ The ` session ` object is available when the user is signed in .
156
152
157
- Returns a promise.
153
+ Example usage:
154
+
155
+ ``` js
156
+ cognito .session .jwtToken ;
157
+ ```
158
158
159
- ### updateResetPassword({ username, code, newPassword })
159
+ It provides the following functionality:
160
160
161
- Set a new password for a user.
161
+ ### ` jwtToken `
162
+
163
+ The current JWT access token.
164
+ This is a tracked property and may be updated in the background.
165
+
166
+ ### ` getAccessToken() `
167
+
168
+ Get the AWS access token object.
169
+ This includes metadata.
170
+
171
+ ### ` getIdToken() `
172
+
173
+ Get the AWS id token object.
174
+ This includes metadata.
175
+
176
+ ### ` needsRefresh() `
177
+
178
+ Returns true if the session is expired.
179
+
180
+ ### ` needsRefreshSoon() `
181
+
182
+ Returns true if the session will expire soon (in the next 15 minutes).
183
+
184
+ ### ` secondsUntilExpires() `
185
+
186
+ Returns the number of seconds until the session will expire.
187
+
188
+ ### ` refresh() `
189
+
190
+ Refresh the session, generating new JWT tokens.
191
+
192
+ This will debounce when being run multiple times simultaneously.
162
193
163
194
Returns a promise.
164
195
165
- ### setNewPassword({ username, password, newPassword })
196
+ ### ` refreshIfNeeded() `
166
197
167
- Set a new password, if a user requires a new password to be set (e.g. after an admin created the user).
198
+ Refresh the session only if it will expire soon.
199
+
200
+ This will debounce when being run multiple times simultaneously.
168
201
169
202
Returns a promise.
170
203
171
- ### updatePassword({ oldPassword, newPassword })
204
+ ## user
205
+
206
+ The ` user ` object is available when the user is signed in.
207
+
208
+ Example usage:
209
+
210
+ ``` js
211
+ cognito .user .updatePassword ({ oldPassword, newPassword });
212
+ ```
213
+
214
+ It provides the following functionality:
215
+
216
+ ### ` userAttributes `
217
+
218
+ This tracked property provides access to a key-value pair object of user attributes.
219
+
220
+ ### ` updatePassword({ oldPassword, newPassword }) `
172
221
173
222
Update the password of the currently logged in user.
174
223
175
224
Returns a promise.
176
225
177
- ## Token expiration
226
+ ### ` updateAttributes(attributes) `
227
+
228
+ Update the attributes of the currently logged in user.
229
+
230
+ This expects an object with key-value pairs, e.g.:
231
+
232
+ ``` js
233
+ user .updateAttributes ({ Email: ' my@email.com' , Name: ' John Doe' });
234
+ ```
235
+
236
+ Returns a promise.
237
+
238
+ ### unauthenticated
239
+
240
+ The ` unauthenticated ` object is always available.
241
+
242
+ Example usage:
243
+
244
+ ``` js
245
+ cognito .unauthenticated .triggerResetPasswordMail ({ username });
246
+ ```
247
+
248
+ It provides the following functionality:
249
+
250
+ ### ` verifyUserAuthentication({ username, password }) `
251
+
252
+ Verify only the given username & password.
253
+ This will _ not_ sign the user in, but can be used to e.g. guard special places in your app behind a repeated password check.
254
+ Will reject with an Error, or resolve if successfull.
255
+
256
+ ### ` triggerResetPasswordMail({ username }) `
257
+
258
+ Trigger an email to get a verification code to reset the password.
259
+
260
+ Returns a promise.
261
+
262
+ ### ` updateResetPassword({ username, code, newPassword }) `
263
+
264
+ Set a new password for a user.
178
265
179
- This addon will automatically refresh the JWT Token every 15 minutes before it expires.
180
- The tokens have a lifespan of 60 minutes, so this should ensure that the local token never experies in the middle of a session.
266
+ Returns a promise.
267
+
268
+ ### ` setInitialPassword({ username, password, newPassword }) `
269
+
270
+ Set a new password, if a user requires a new password to be set (e.g. after an admin created the user).
271
+
272
+ Returns a promise.
181
273
182
- ## Multi-Factor Authentication (MFA )
274
+ ## mfa ( Multi-Factor Authentication)
183
275
184
276
This addon allows you to work with optional TOTP (Temporary One Time Password) MFA.
185
277
SMS-based MFA is not supported for now (to reduce complexity, and since it is less secure than TOTP).
@@ -190,10 +282,10 @@ Using MFA in your app requires changes in two places: The sign in process, and a
190
282
191
283
### Setting up MFA
192
284
193
- A user can opt into MFA for their own account. For this, you can use the ` mfa ` object on the ` cognitoData ` object:
285
+ A user can opt into MFA for their own account. For this, you can use the ` mfa ` object on the ` user ` object:
194
286
195
287
``` js
196
- let { mfa } = this .cognito .cognitoData ;
288
+ let { mfa } = this .cognito .user ;
197
289
198
290
// Available methods
199
291
await mfa .enable ();
@@ -277,6 +369,16 @@ await this.cognito.mfaCompleteAuthentication(mfaCode);
277
369
278
370
After that, the user will be signed in (or it will throw an error if the MFA code is incorrect).
279
371
372
+ ## Token expiration
373
+
374
+ The generated JWT tokens have a lifespan of 60 minutes. After that, you need to refresh the session.
375
+
376
+ You can call ` cognito.session.enableAutoRefresh() ` to start an automated background job,
377
+ which will refresh the token every 45 minutes.
378
+
379
+ Alternatively, you can also manually handle this with the provided ` session.needsRefresh() ` ,
380
+ ` session.needsRefreshSoon() ` , ` session.refresh() ` and ` session.refreshIfNeeded() ` methods.
381
+
280
382
## Example
281
383
282
384
You can find example components in the dummy app to see how a concrete implementation could look like.
@@ -371,7 +473,7 @@ test('it works with new password required', function (assert) {
371
473
372
474
### Generating mocked data
373
475
374
- You can generate mocked cognitoData with the provided utils:
476
+ You can generate a mocked user/session with the provided utils:
375
477
376
478
``` js
377
479
import ApplicationInstance from ' @ember/application/instance' ;
@@ -383,7 +485,7 @@ export function initialize(appInstance: ApplicationInstance): void {
383
485
let cognitoData = mockCognitoData ();
384
486
if (cognitoData) {
385
487
let cognito = appInstance .lookup (' service:cognito' );
386
- cognito .cognitoData = cognitoData ;
488
+ cognito .setupSession ( cognitoData) ;
387
489
}
388
490
}
389
491
@@ -453,7 +555,7 @@ test('test helper correctly mocks a cognito session', async function (assert) {
453
555
assert,
454
556
});
455
557
456
- cognito .cognitoData = cognitoData ;
558
+ cognito .setupSession ( cognitoData) ;
457
559
});
458
560
```
459
561
0 commit comments