forked from jagregory/cognito-local
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(api): finish implementation of changePassword
- Loading branch information
Showing
4 changed files
with
258 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { withCognitoSdk } from "./setup"; | ||
|
||
describe( | ||
"CognitoIdentityServiceProvider.changePassword", | ||
withCognitoSdk((Cognito) => { | ||
it("deletes the current user", async () => { | ||
const client = Cognito(); | ||
|
||
// create the user pool client | ||
const upc = await client | ||
.createUserPoolClient({ | ||
UserPoolId: "test", | ||
ClientName: "test", | ||
}) | ||
.promise(); | ||
|
||
// create a user | ||
await client | ||
.adminCreateUser({ | ||
DesiredDeliveryMediums: ["EMAIL"], | ||
TemporaryPassword: "def", | ||
UserAttributes: [{ Name: "email", Value: "[email protected]" }], | ||
Username: "abc", | ||
UserPoolId: "test", | ||
}) | ||
.promise(); | ||
|
||
await client | ||
.adminSetUserPassword({ | ||
Password: "firstPassword", | ||
Permanent: true, | ||
Username: "abc", | ||
UserPoolId: "test", | ||
}) | ||
.promise(); | ||
|
||
// login | ||
const initAuthResponse = await client | ||
.initiateAuth({ | ||
ClientId: upc.UserPoolClient?.ClientId!, | ||
AuthFlow: "USER_PASSWORD_AUTH", | ||
AuthParameters: { | ||
USERNAME: "abc", | ||
PASSWORD: "firstPassword", | ||
}, | ||
}) | ||
.promise(); | ||
|
||
// delete the user with their token | ||
await client | ||
.changePassword({ | ||
AccessToken: initAuthResponse.AuthenticationResult?.AccessToken!, | ||
PreviousPassword: "firstPassword", | ||
ProposedPassword: "secondPassword", | ||
}) | ||
.promise(); | ||
|
||
// (fail to) login with the old password | ||
await expect( | ||
client | ||
.initiateAuth({ | ||
ClientId: upc.UserPoolClient?.ClientId!, | ||
AuthFlow: "USER_PASSWORD_AUTH", | ||
AuthParameters: { | ||
USERNAME: "abc", | ||
PASSWORD: "firstPassword", | ||
}, | ||
}) | ||
.promise() | ||
).rejects.toBeDefined(); | ||
|
||
// login with the new password | ||
const initAuthResponse2nd = await client | ||
.initiateAuth({ | ||
ClientId: upc.UserPoolClient?.ClientId!, | ||
AuthFlow: "USER_PASSWORD_AUTH", | ||
AuthParameters: { | ||
USERNAME: "abc", | ||
PASSWORD: "secondPassword", | ||
}, | ||
}) | ||
.promise(); | ||
|
||
expect(initAuthResponse2nd).toBeDefined(); | ||
}); | ||
}) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import jwt from "jsonwebtoken"; | ||
import * as uuid from "uuid"; | ||
import { ClockFake } from "../__tests__/clockFake"; | ||
import { newMockCognitoService } from "../__tests__/mockCognitoService"; | ||
import { newMockUserPoolService } from "../__tests__/mockUserPoolService"; | ||
import { TestContext } from "../__tests__/testContext"; | ||
import * as TDB from "../__tests__/testDataBuilder"; | ||
import { | ||
InvalidParameterError, | ||
InvalidPasswordError, | ||
NotAuthorizedError, | ||
} from "../errors"; | ||
import PrivateKey from "../keys/cognitoLocal.private.json"; | ||
import { UserPoolService } from "../services"; | ||
import { ChangePassword, ChangePasswordTarget } from "./changePassword"; | ||
|
||
const currentDate = new Date(); | ||
|
||
describe("ChangePassword target", () => { | ||
let changePassword: ChangePasswordTarget; | ||
let mockUserPoolService: jest.Mocked<UserPoolService>; | ||
|
||
beforeEach(() => { | ||
mockUserPoolService = newMockUserPoolService(); | ||
changePassword = ChangePassword({ | ||
cognito: newMockCognitoService(mockUserPoolService), | ||
clock: new ClockFake(currentDate), | ||
}); | ||
}); | ||
|
||
it("throws if token isn't valid", async () => { | ||
await expect( | ||
changePassword(TestContext, { | ||
AccessToken: "blah", | ||
PreviousPassword: "abc", | ||
ProposedPassword: "def", | ||
}) | ||
).rejects.toBeInstanceOf(InvalidParameterError); | ||
|
||
expect(mockUserPoolService.saveUser).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it("throws if user doesn't exist", async () => { | ||
mockUserPoolService.getUserByUsername.mockResolvedValue(null); | ||
|
||
await expect( | ||
changePassword(TestContext, { | ||
AccessToken: jwt.sign( | ||
{ | ||
sub: "0000-0000", | ||
event_id: "0", | ||
token_use: "access", | ||
scope: "aws.cognito.signin.user.admin", | ||
auth_time: new Date(), | ||
jti: uuid.v4(), | ||
client_id: "test", | ||
username: "0000-0000", | ||
}, | ||
PrivateKey.pem, | ||
{ | ||
algorithm: "RS256", | ||
issuer: `http://localhost:9229/test`, | ||
expiresIn: "24h", | ||
keyid: "CognitoLocal", | ||
} | ||
), | ||
PreviousPassword: "abc", | ||
ProposedPassword: "def", | ||
}) | ||
).rejects.toEqual(new NotAuthorizedError()); | ||
|
||
expect(mockUserPoolService.saveUser).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it("throws if previous password doesn't match", async () => { | ||
const user = TDB.user({ | ||
Password: "previous-password", | ||
}); | ||
|
||
mockUserPoolService.getUserByUsername.mockResolvedValue(user); | ||
|
||
await expect( | ||
changePassword(TestContext, { | ||
AccessToken: jwt.sign( | ||
{ | ||
sub: "0000-0000", | ||
event_id: "0", | ||
token_use: "access", | ||
scope: "aws.cognito.signin.user.admin", | ||
auth_time: new Date(), | ||
jti: uuid.v4(), | ||
client_id: "test", | ||
username: "0000-0000", | ||
}, | ||
PrivateKey.pem, | ||
{ | ||
algorithm: "RS256", | ||
issuer: `http://localhost:9229/test`, | ||
expiresIn: "24h", | ||
keyid: "CognitoLocal", | ||
} | ||
), | ||
PreviousPassword: "abc", | ||
ProposedPassword: "def", | ||
}) | ||
).rejects.toEqual(new InvalidPasswordError()); | ||
|
||
expect(mockUserPoolService.saveUser).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it("updates the user's password if the previous password matches", async () => { | ||
const user = TDB.user({ | ||
Password: "previous-password", | ||
}); | ||
|
||
mockUserPoolService.getUserByUsername.mockResolvedValue(user); | ||
|
||
await changePassword(TestContext, { | ||
AccessToken: jwt.sign( | ||
{ | ||
sub: "0000-0000", | ||
event_id: "0", | ||
token_use: "access", | ||
scope: "aws.cognito.signin.user.admin", | ||
auth_time: new Date(), | ||
jti: uuid.v4(), | ||
client_id: "test", | ||
username: "0000-0000", | ||
}, | ||
PrivateKey.pem, | ||
{ | ||
algorithm: "RS256", | ||
issuer: `http://localhost:9229/test`, | ||
expiresIn: "24h", | ||
keyid: "CognitoLocal", | ||
} | ||
), | ||
PreviousPassword: "previous-password", | ||
ProposedPassword: "new-password", | ||
}); | ||
|
||
expect(mockUserPoolService.saveUser).toHaveBeenCalledWith(TestContext, { | ||
...user, | ||
Password: "new-password", | ||
UserLastModifiedDate: currentDate, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters