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

Enable MFA on specific API keys #2846

Merged
merged 3 commits into from
Dec 28, 2021
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion app/assets/stylesheets/modules/form.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
.form__input__addon-left .form__input {
padding-left: 45px; }

.form__input, .form__textarea, .form__select {
.form__input, .form__textarea, .form__select, .form__group {
margin-bottom: 30px; }

.form__input, .form__textarea {
Expand Down
7 changes: 7 additions & 0 deletions app/assets/stylesheets/modules/owners.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ span.owners__icon img {
padding-right: 2px;
}

.owners__cell[data-title="MFA"] img {
margin: auto 0;
height: 23px;
width: 23px;
border-radius: 50%;
}

@media screen and (max-width: 640px) {
.owners__tbody {
display: block;
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def enqueue_web_hook_jobs(version)

def verify_with_otp
otp = request.headers["HTTP_OTP"]
return if @api_key.user.mfa_api_authorized?(otp)
return if @api_key.mfa_authorized?(otp)
prompt_text = otp.present? ? t(:otp_incorrect) : t(:otp_missing)
render plain: prompt_text, status: :unauthorized
end
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/api/v1/api_keys_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ def otp
end

def api_key_create_params
params.permit(:name, *ApiKey::API_SCOPES)
params.permit(:name, *ApiKey::API_SCOPES, :mfa)
sonalkr132 marked this conversation as resolved.
Show resolved Hide resolved
end

def api_key_update_params
params.permit(*ApiKey::API_SCOPES)
params.permit(*ApiKey::API_SCOPES, :mfa)
end
end
2 changes: 1 addition & 1 deletion app/controllers/api_keys_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def reset
private

def api_key_params
params.require(:api_key).permit(:name, *ApiKey::API_SCOPES)
params.require(:api_key).permit(:name, *ApiKey::API_SCOPES, :mfa)
end

def redirect_to_verify
Expand Down
10 changes: 10 additions & 0 deletions app/models/api_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ def enabled_scopes
end
end

def mfa_authorized?(otp)
return true unless mfa_enabled?
user.otp_verified?(otp)
end

def mfa_enabled?
return false unless user.mfa_enabled?
user.mfa_ui_and_api? || mfa
end

private

def exclusive_show_dashboard_scope
Expand Down
5 changes: 0 additions & 5 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,6 @@ def mfa_gem_signin_authorized?(otp)
otp_verified?(otp)
end

def mfa_api_authorized?(otp)
return true unless mfa_ui_and_api?
otp_verified?(otp)
end

def otp_verified?(otp)
otp = otp.to_s
return true if verify_digit_otp(mfa_seed, otp)
Expand Down
22 changes: 17 additions & 5 deletions app/views/api_keys/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@
<%= label_tag :name, t("api_keys.index.name"), class: "form__label" %>
<%= f.text_field :name, class: "form__input", autocomplete: :off %>

<%= label_tag :scope, t("api_keys.index.scope"), class: "form__label" %>
<% ApiKey::API_SCOPES.each do |api_scope| %>
<div class = "form__checkbox__item">
<%= f.check_box "#{api_scope}", { class: "form__checkbox__input", id: "#{api_scope}" } , "true", "false" %>
<%= label_tag api_scope, t("api_keys.index.#{api_scope}"), class: "form__checkbox__label" %>
<div class="form__group">
<%= label_tag :scope, t("api_keys.index.scope"), class: "form__label" %>
<% ApiKey::API_SCOPES.each do |api_scope| %>
<div class = "form__checkbox__item">
<%= f.check_box "#{api_scope}", { class: "form__checkbox__input", id: "#{api_scope}" } , "true", "false" %>
<%= label_tag api_scope, t("api_keys.index.#{api_scope}"), class: "form__checkbox__label" %>
</div>
<% end %>
</div>

<% unless current_user.mfa_disabled? || current_user.mfa_ui_and_api? %>
<div class="form__group">
<%= label_tag :mfa, t(".multifactor_auth"), class: "form__label" %>
<div class="form__checkbox__item">
<%= f.check_box :mfa, { class: "form__checkbox__input", id: :mfa } , "true", "false" %>
<%= label_tag :mfa, t(".enable_mfa"), class: "form__checkbox__label" %>
</div>
</div>
<% end %>

Expand Down
14 changes: 14 additions & 0 deletions app/views/api_keys/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
<th class="owners__cell">
<%= t(".age") %>
</th>
<% if current_user.mfa_enabled? %>
<th class="owners__cell">
<%= t(".mfa") %>
</th>
<% end %>
<th class="owners__cell">
<%= t(".last_access") %>
</th>
Expand All @@ -41,6 +46,11 @@
<td class="owners__cell" data-title="Age">
<%= time_ago_in_words(api_key.created_at) %>
</td>
<% if current_user.mfa_enabled? %>
<td class="owners__cell" data-title="MFA">
<%= image_tag("/images/check.svg") if api_key.mfa? %>
</td>
<% end %>
<td class="owners__cell" data-title="Last access">
<%= api_key.last_accessed_at&.strftime("%Y-%m-%d %H:%M %Z") %>
</td>
Expand Down Expand Up @@ -70,6 +80,10 @@
</td>
<td class="owners__cell">
</td>
<% if current_user.mfa_enabled? %>
<td class="owners__cell">
</td>
<% end %>
<td class="owners__cell">
<%= button_to t(".reset"),
reset_profile_api_keys_path,
Expand Down
22 changes: 17 additions & 5 deletions app/views/api_keys/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@
<%= label_tag :name, t("api_keys.index.name"), class: "form__label" %>
<%= f.text_field :name, class: "form__input", autocomplete: :off %>

<%= label_tag :scope, t("api_keys.index.scope"), class: "form__label" %>
<% ApiKey::API_SCOPES.each do |api_scope| %>
<div class = "form__checkbox__item">
<%= f.check_box "#{api_scope}", { class: "form__checkbox__input", id: "#{api_scope}" } , "true", "false" %>
<%= label_tag api_scope, t("api_keys.index.#{api_scope}"), class: "form__checkbox__label" %>
<div class="form__group">
<%= label_tag :scope, t("api_keys.index.scope"), class: "form__label" %>
<% ApiKey::API_SCOPES.each do |api_scope| %>
<div class = "form__checkbox__item">
<%= f.check_box "#{api_scope}", { class: "form__checkbox__input", id: "#{api_scope}" } , "true", "false" %>
<%= label_tag api_scope, t("api_keys.index.#{api_scope}"), class: "form__checkbox__label" %>
</div>
<% end %>
</div>

<% if current_user.mfa_enabled? %>
<div class="form__group">
<%= label_tag :mfa, t(".multifactor_auth"), class: "form__label" %>
<div class="form__checkbox__item">
<%= f.check_box :mfa, { class: "form__checkbox__input", id: :mfa, checked: true } , "true", "false" %>
<%= label_tag :mfa, t(".enable_mfa"), class: "form__checkbox__label" %>
</div>
</div>
<% end %>

Expand Down
5 changes: 5 additions & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,19 @@ de:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,19 @@ en:
show_dashboard: Show dashboard
reset: Reset
save_key: "Note that we won't be able to show the key to you again. New API key:"
mfa: MFA
new:
new_api_key: New API key
multifactor_auth: Multifactor authentication
enable_mfa: Enable MFA
reset:
success: "Deleted all API keys"
update:
success: "Successfully updated API key"
edit:
edit_api_key: "Edit API key"
multifactor_auth: Multifactor authentication
enable_mfa: Enable MFA
clearance_mailer:
change_password:
title: CHANGE PASSWORD
Expand Down
5 changes: 5 additions & 0 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,19 @@ es:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title: CAMBIAR CONTRASEÑA
Expand Down
5 changes: 5 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,19 @@ fr:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,19 @@ ja:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions config/locales/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,19 @@ nl:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,19 @@ pt-BR:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions config/locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,19 @@ zh-CN:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions config/locales/zh-TW.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,19 @@ zh-TW:
show_dashboard:
reset:
save_key:
mfa:
new:
new_api_key:
multifactor_auth:
enable_mfa:
reset:
success:
update:
success:
edit:
edit_api_key:
multifactor_auth:
enable_mfa:
clearance_mailer:
change_password:
title:
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20211027170037_add_mfa_column_to_api_keys.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddMfaColumnToApiKeys < ActiveRecord::Migration[6.1]
def change
add_column :api_keys, :mfa, :boolean, default: false, null: false
end
end
1 change: 1 addition & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
t.datetime "last_accessed_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "mfa", default: false, null: false
t.index ["hashed_key"], name: "index_api_keys_on_hashed_key", unique: true
t.index ["user_id"], name: "index_api_keys_on_user_id"
end
Expand Down
Loading