Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove recovery codes for MFA #712

Closed
wants to merge 99 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
dfe23f0
Initial HTML and JS for enabling MFA on user account through dashboard
Nov 16, 2021
baf4fe8
Button and modal for editing MFA settings now appears
Nov 18, 2021
577f5cb
Adding modal for enabling authenticator app
Nov 19, 2021
0a58578
Adding models for IamTotpMfa and IamTotpRecoveryCode
Nov 19, 2021
6fd8ccc
Adding modal for disabling authenticator app
Nov 19, 2021
dccc0b6
Merge branch 'iam-spring-update-oct-2021' of git://github.com/indigo-…
Nov 22, 2021
1a08d05
WIP: Increase the Cookie duration
rmiccoli Sep 2, 2021
fb229df
Allow config option in test client app to avoid disclosing tokens
andreaceccanti Sep 10, 2021
02ac0d2
Dynamic downscoping in test client app
andreaceccanti Sep 11, 2021
a2dcabb
Bumped version to v1.7.1
andreaceccanti Sep 11, 2021
80b3140
v1.7.1 changelog
andreaceccanti Sep 11, 2021
855ee1e
More CHANGELOG tweaks
andreaceccanti Sep 11, 2021
8943042
Initial HTML and JS for enabling MFA on user account through dashboard
Nov 16, 2021
900662c
Button and modal for editing MFA settings now appears
Nov 18, 2021
dc787f8
Adding modal for enabling authenticator app
Nov 19, 2021
474b287
Adding models for IamTotpMfa and IamTotpRecoveryCode
Nov 19, 2021
c7dd5be
Adding modal for disabling authenticator app
Nov 19, 2021
d77143b
Unifying controllers, adding auth app service
Nov 22, 2021
fac0a90
Merge branch 'issue-418-mfa-support' of https://github.com/sam-glende…
Nov 22, 2021
67d80a1
Syncing branch with origin
Nov 22, 2021
af13c9c
Merging changes for updating Spring boot and Java version. Squashed c…
Nov 22, 2021
e6e8b26
Making database schema changes for MySQL and H2
Nov 23, 2021
84c8434
Ignoring .factorypath autogenerated file
Nov 23, 2021
ccbc081
Backend for adding TOTP secret to a user
Nov 24, 2021
409adb4
Merge branch 'iam-spring-update-oct-2021' into issue-418-mfa-support
Nov 25, 2021
47baf5f
Merge branch 'iam-spring-update-oct-2021' of git://github.com/indigo-…
Nov 25, 2021
70469af
Merge branch 'iam-spring-update-oct-2021' into issue-418-mfa-support
Nov 25, 2021
ae8b887
Removing non-existent files
Nov 25, 2021
1be4737
MFA secret and QR code now display on authenticator app enabling modal
Nov 25, 2021
06f4ace
Dynamic mfa settings menu, toaster notifications on successful operation
Nov 26, 2021
3fb7e55
Adding license to files, adding basic input detection for MFA modals
Nov 26, 2021
ea1a536
Verification code now sends through post successfully
Nov 29, 2021
5b23238
Adding TOTP validation for enabling and disabling authenticator app MFA
Nov 29, 2021
e89f821
Autowiring QR generator and code verifier into AuthenticatorAppContro…
Nov 29, 2021
c4be542
Database migrations for totp_mfa now in separate file
Nov 30, 2021
dea8ff5
Adding tests for enabling and disabling TOTP MFA through IamAccountSe…
Nov 30, 2021
b794327
Adding tests for MFA settings and auth app controllers
Dec 1, 2021
0a0557c
Adding ROLE_PRE_AUTHENTICATED
Dec 2, 2021
b1dc5fe
Adding UUID for IamTotpMfa, fixing migration version numbers
Dec 2, 2021
cc77a0b
Removing UUID from IamTotpMfa due to being unnecessary
Dec 2, 2021
27c0e65
Adding java docs for files in iam-login-service
Dec 3, 2021
81b536f
Adding basic mfa login procedure
Dec 6, 2021
f0de8a8
Merge branch 'indigo-iam:iam-spring-update-oct-2021' into iam-spring-…
Dec 6, 2021
fafd97e
Merge branch 'iam-spring-update-oct-2021' into issue-418-mfa-support
Dec 6, 2021
c9feb7c
Improving TOTP input screen post-login, fixing Java 17 Docker upgrade…
Dec 7, 2021
b05cce2
Adding error handling for MFA failure, fixing CSS bugs
Dec 8, 2021
f67d9b7
Separating MFA verification controllers, adding "Back to login" button
Dec 8, 2021
82af215
Adding mechanism for looping through available factors of authenticat…
Dec 9, 2021
3479f43
Adding recovery code login procedure, backend for regenerating recove…
Dec 10, 2021
915c6a9
Fixing css bug that broke the btn-login class
Dec 13, 2021
6a13643
Fixing css bugs with MFA verify button
Dec 13, 2021
e13a169
Adding recovery code regeneration after use and webpage navigation
Dec 13, 2021
ad2b1ad
Adding ability to view and reset recovery codes
Dec 14, 2021
d378875
Fixing error message tests in AuthenticatorAppSettingsTests
Dec 14, 2021
a0d900d
Fixing enabling and disabing totpMfa tests for IamAccount
Dec 15, 2021
79e5248
Adding tests for MfaVerify and AuthenticatorAppVerify controllers
Dec 16, 2021
ffa735a
Adding licence header
Dec 16, 2021
4741225
Adding tests for recovery code management controller endpoints
Dec 17, 2021
7c997a0
Adding tests on account service for adding recovery codes, fixing clo…
Dec 17, 2021
48b89c2
Fixing submit button bug on dashboard modals
Jan 6, 2022
b018fe3
Recovery codes display to the user on MFA enabling
Jan 6, 2022
8a33dc8
Adding amr claim in OIDC id_token
Jan 17, 2022
4efb960
Removing unnecessary database migrations, extending authentication ob…
Jan 20, 2022
6ac8b54
Fixing login bugs with MfaAuthenticationToken, extending authenticati…
Jan 21, 2022
54842ff
Renaming MfaAuthenticationToken to ExtendedAuthenticationToken
Jan 21, 2022
2a03fbb
Renaming MfaAuthenticationFilter to ExtendedAuthenticationFilter
Jan 21, 2022
2c946de
Moving db migrations to correct directory
Jan 24, 2022
98d3c73
Removing unneeded method to regenerate recovery codes
Jan 24, 2022
f095d71
Adding creation time and update time to IamTotpMfa
Jan 24, 2022
f2af341
Fixing migrations from IamTotpMfa creation and update time fields
Jan 27, 2022
a7098a6
Removing YubiKey option and all references in code
Jan 27, 2022
143dfe1
Demonstrating reading of amr from request parameters to /token
Feb 3, 2022
a062373
Authentication method reference claim now successfully appears in id_…
Feb 17, 2022
666037b
OAuth2 client login flow now works for MFA users
Feb 24, 2022
11cbc2c
Fixing login credential failure handling
Feb 25, 2022
dc01d78
Fixing TOTP verification process
Feb 25, 2022
3553f26
Merging base branch and fixing conflicts
Feb 28, 2022
a231f5e
Adding recovery code verification to login flow
Mar 4, 2022
e34f016
Merge branch mfa-db-migrations into issue-418-mfa-support
Mar 4, 2022
bc39b71
Merge branch 'v1.8.0' into issue-418-mfa-support
Mar 4, 2022
6513b09
Adding comments, fixing assigned authorities bug
Mar 8, 2022
d9b461e
Merge branch 'issue-418-mfa-support' of https://github.com/sam-glende…
Mar 8, 2022
e6750ec
Fixing license header in verify JSP
Mar 8, 2022
566b1f3
Fixing existing MFA tests, improving controller functionality
Mar 10, 2022
958082c
Adding license header for IamTotpMfaServiceTests
Mar 10, 2022
469ac8e
Fixing bugs with MFA verification
Mar 11, 2022
6f5ceb4
Merge remote-tracking branch 'sam/issue-418-mfa-support' into issue-418
rmiccoli Oct 19, 2023
13f27b4
Fix MFA settings view
rmiccoli Oct 19, 2023
bd9764d
Fix tests
rmiccoli Oct 23, 2023
bd69d32
Fix some test
federicaagostini Oct 24, 2023
47c7246
Fix other tests
rmiccoli Oct 24, 2023
d39fa6f
Update Spring Security OAuth2 Client dependency
rmiccoli Oct 27, 2023
5314ec9
Add download recovery codes button
Sae126V Nov 21, 2023
447f1be
Delete recovery codes from the interface
rmiccoli Feb 9, 2024
bcc4e29
Remove recovery codes generator and verifier
rmiccoli Feb 12, 2024
4f026bb
Fix test
rmiccoli Feb 12, 2024
9e31402
Try to fix infinite recursion problem
rmiccoli Feb 12, 2024
fb7be0b
Add jackson dependency
rmiccoli Feb 13, 2024
82f6943
Implement the Serializable interface
rmiccoli Feb 13, 2024
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
Prev Previous commit
Next Next commit
Initial HTML and JS for enabling MFA on user account through dashboard
Files are not complete, work still to be done on creating and displaying the angular components
  • Loading branch information
Sam Glendenning committed Nov 22, 2021
commit 894304280007d0dc7bcb56077a6c2963f4a52271
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--

Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2019

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->
<!-- Edit details button -->
<button class="btn btn-primary btn-block" ng-click="$ctrl.openUserMfaModal()" ng-enabled="$ctrl.enabled" name="user-mfa-btn">
<i class="fa fa-pencil"></i>
<strong>Edit multi-factor settings</strong>
</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2019
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';

function UserMfaController(
toaster, Utils, ModalService, $uibModal) {
var self = this;

self.$onInit = function() {
console.log('UserMfaController onInit');
self.enabled = true;
self.user = self.userCtrl.user;
};

self.isMe = function() { return self.userCtrl.isMe(); };

self.openUserMfaModal = function() {
self.enabled = false;
var modalInstance = $uibModal.open({
templateUrl: '/resources/iam/apps/dashboard-app/templates/home/editmfasettings.html',
controller: 'UserMfaController',
controllerAs: 'userMfaCtrl',
resolve: {user: function() { return self.user; }}
});

modalInstance.result.then(function(msg) {
toaster.pop({type: 'success', body: msg});
});
};
}



angular.module('dashboardApp').component('userMfa', {
require: {userCtrl: '^user'},
templateUrl:
'/resources/iam/apps/dashboard-app/components/user/mfa/user.mfa.component.html',
controller: [
'toaster', 'Utils', 'ModalService', '$uibModal',
UserMfaController
]
});
})();
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ <h1>
<!-- Send reset password email or change password-->
<user-password user="$ctrl.user"></user-password>

<!-- Change multi-factor authentication settings -->
<user-mfa user="$ctrl.user"></user-mfa>

</div>
</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!--

Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2019

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->
<form class="form-horizontal" ng-submit="userMfaCtrl.submit()" name="userMfaForm">

<div class="modal-header">
<h3 class="modal-title">Edit multi-factor authentication settings for '{{userMfaCtrl.eUser.name.formatted}}'</h3>
</div>

<div class="modal-body">
<operationresult/>

<div class="form-group">
<label class="control-label col-sm-2" for="name">Authenticator app</label>
<!-- Some of this is stolen from Status section in user.detail component -->
<td class="text-right">
<span class="label label-success" ng-show="$ctrl.user.mfa.authenticatorAppActive">
<i class="fa fa-check"></i> Enabled
</span>
<button class="btn btn-danger" type="button" name="disable-authenticator-app" id="disable-authenticator-app-btn" ng-show="$ctrl.user.mfa.authenticatorAppActive" ng-click="userMfaCtrl.disableAuthenticatorApp()">Disable</button>
<span class="label label-warning" ng-show="!$ctrl.user.mfa.authenticatorAppActive">
<i class="fa fa-check"></i> Disabled
</span>
<button class="btn btn-primary" type="button" name="enable-authenticator-app" id="enable-authenticator-app-btn" ng-show="!$ctrl.user.mfa.authenticatorAppActive" ng-click="userMfaCtrl.enableAuthenticatorApp()">Enable</button>
</td>
</div>

<div class="form-group">
<label class="control-label col-sm-2" for="name">YubiKey</label>
<!-- Some of this is stolen from Status section in user.detail component -->
<td class="text-right">
<span class="label label-success" ng-show="$ctrl.user.mfa.yubikeyActive">
<i class="fa fa-check"></i> Enabled
</span>
<button class="btn btn-danger" type="button" name="disable-yubikey" id="disable-yubikey-btn" ng-show="$ctrl.user.mfa.yubikeyActive" ng-click="userMfaCtrl.disableYubiKey()">Disable</button>
<span class="label label-warning" ng-show="!$ctrl.user.mfa.yubikeyActive">
<i class="fa fa-check"></i> Disabled
</span>
<button class="btn btn-primary" type="button" name="enable-yubikey" id="enable-yubikey-btn" ng-show="!$ctrl.user.mfa.yubikeyActive" ng-click="userMfaCtrl.enableYubiKey()">Enable</button>
</td>
</div>

<!-- <div class="form-group">
<label class="control-label col-sm-2" for="surname">Surname</label>
<div ng-class="{'has-error': userMfaForm.surname.$dirty && userMfaForm.surname.$invalid, 'has-success': userMfaForm.surname.$dirty && userMfaForm.surname.$valid}">
<div class="col-sm-10">
<input class="form-control" name="surname" id="surname" type="text" ng-model="userMfaCtrl.eUser.surname" placeholder="Family name" required ng-minlength="3"/>
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-remove': userMfaForm.surname.$dirty && userMfaForm.surname.$invalid, 'glyphicon-ok': userMfaForm.surname.$dirty && userMfaForm.surname.$valid}" style="right: 15px"></span>
<span class="help-block" ng-show="userMfaForm.surname.$dirty && userMfaForm.surname.$error.required">
This is a required field</span>
<span class="help-block" ng-show="userMfaForm.surname.$dirty && userMfaForm.surname.$error.minlength">Minimum length required is 3</span>
</div>
</div>
</div>

<div class="form-group">
<label class="control-label col-sm-2" for="email">Email</label>
<div ng-class="{'has-error': userMfaForm.email.$dirty && userMfaForm.email.$invalid, 'has-success': userMfaForm.email.$dirty && userMfaForm.email.$valid}">
<div class="col-sm-10">
<input class="form-control"
name="email" id="email" type="email"
ng-model="userMfaCtrl.eUser.email"
placeholder="Email"
required ng-minlength="3"
iam-email-available-validator />

<span class="glyphicon form-control-feedback"
ng-class="{'glyphicon-remove': userMfaForm.email.$dirty && userMfaForm.email.$invalid, 'glyphicon-ok': userMfaForm.email.$dirty && userMfaForm.email.$valid}" style="right: 15px"></span>

<span class="help-block" ng-show="userMfaForm.email.$dirty && userMfaForm.email.$error.required">
This is a required field
</span>

<span class="help-block" ng-show="userMfaForm.email.$dirty && userMfaForm.email.$error.email">
This is not a valid email
</span>

<span class="help-block" ng-show="userMfaForm.email.$dirty && userMfaForm.email.$error.emailAvailable">
Email already taken by another user
</span>
</div>
</div>
</div>

<div class="form-group">
<label class="control-label col-sm-2" for="picture">Picture</label>
<div ng-class="{'has-error': userMfaForm.picture.$dirty && userMfaForm.picture.$invalid, 'has-success': userMfaForm.picture.$dirty && userMfaForm.picture.$valid}">
<div class="col-sm-10">
<input class="form-control" id="picture" name="picture" type="url" ng-model="userMfaCtrl.eUser.picture"/>
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-remove': userMfaForm.picture.$dirty && userMfaForm.picture.$invalid, 'glyphicon-ok': userMfaForm.picture.$dirty && userMfaForm.picture.$valid}" style="right: 15px"></span>
<span class="help-block" ng-show="userMfaForm.picture.$dirty && userMfaForm.picture.$invalid">This field is invalid</span>
<span class="help-block" ng-show="userMfaForm.picture.$dirty && userMfaForm.picture.$error.url">
This field is not a valid URL</span>
</div>
<div class="col-sm-12">
<br/>
<img ng-src="{{userMfaCtrl.eUser.picture}}" ng-show="userMfaCtrl.eUser.picture" class="profile-user-img img-responsive img-circle"/>
</div>
</div>
</div> -->

</div>

<div class="modal-footer">
<button class="btn btn-danger" type="button" name="dismiss" id="modal-btn-cancel" ng-click="userMfaCtrl.dismiss()">Cancel</button>
</div>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<!--

Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2019

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->

<form class="form-horizontal" ng-submit="enableAuthenticatorAppCtrl.submit()" name="enableAuthenticatorAppForm">

<div class="modal-header">
<h3 class="modal-title">Enable authenticator app</h3>
</div>

<div class="modal-body">
<operationresult />

<img th:src="${dataUri}" />
<p>Alternatively, enter this secret manually into the app.</p>
<p th:text="${secret}">...</p>

<div class="form-group">
<div class="col-sm-3">
<label class="control-label" for="code">New Code</label>
</div>
<div class="col-sm-9" ng-class="{'has-error': enableAuthenticatorAppForm.code.$dirty && enableAuthenticatorAppForm.code.$invalid, 'has-success': enableAuthenticatorAppForm.code.$dirty && enableAuthenticatorAppForm.code.$valid}">
<input type="text" inputmode="numeric" name="code" class="form-control" ng-model="enableAuthenticatorAppCtrl.user.code" required ng-minlength="enableAuthenticatorAppCtrl.codeMinlength" />
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-remove': enableAuthenticatorAppForm.code.$dirty && enableAuthenticatorAppForm.code.$invalid, 'glyphicon-ok': enableAuthenticatorAppForm.code.$dirty && enableAuthenticatorAppForm.code.$valid}" style="right: 15px"></span>
<span class="help-block" ng-show="enableAuthenticatorAppForm.code.$dirty && enableAuthenticatorAppForm.code.$error.required"> This is a required field</span>
<span class="help-block" ng-show="enableAuthenticatorAppForm.code.$dirty && enableAuthenticatorAppForm.code.$error.minlength">Minimum length required is {{enableAuthenticatorAppCtrl.codeMinlength}}</span>
</div>
</div>

<div class="modal-footer">
<button class="btn btn-primary" type="submit" name="submit" id="modal-btn-submit" ng-disabled="!enableAuthenticatorAppForm.$dirty || enableAuthenticatorAppForm.$invalid || !enableAuthenticatorAppForm.enabled">Submit</button>
<button class="btn btn-warning" type="button" name="reset" id="modal-btn-reset" ng-click="enableAuthenticatorAppForm.reset()" ng-disabled="enableAuthenticatorAppForm.$pristine">Reset</button>
<button class="btn btn-danger" type="button" name="dismiss" id="modal-btn-cancel" ng-click="enableAuthenticatorAppForm.dismiss()">Cancel</button>
</div>

</form>

<!-- HTML as imported from prototype. Not part of final product -->
<div class="container">
<form class="form-signin" method="post" action="/enableAuthenticatorApp">
<h2 class="form-signin-heading">Validate TOTP</h2>
<p>Scan the QR code through your authenticator app and input a TOTP to validate configuration.</p>
<div th:if="${error}">
<p th:text="${error}" style="color: red;">...</p>
</div>
<img th:src="${dataUri}" />
<br>
<br>
<p>Alternatively, enter this secret manually into the app.</p>
<p th:text="${secret}">...</p>
<br>
<br>
<p>
<label for="code" class="sr-only">Username</label>
<input type="text" inputmode="numeric" id="code" name="code" class="form-control" placeholder="Code" required=""
autofocus="">
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Validate</button>
</form>
</div>
Loading