Skip to content

Commit

Permalink
Merge pull request #26 from jsurkont/qr_code
Browse files Browse the repository at this point in the history
feat(QR): add configuration option to disable QR code
  • Loading branch information
tauceti2 authored Jun 1, 2021
2 parents d51a6f2 + fd7c101 commit 9ff1824
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 38 deletions.
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,17 @@ See `config_template.json` (LDAP section is optional).

Edit `/etc/pam_oauth2_device/config.json`.

**qr** - allowed correction levels are

- 0 - low
- 1 - medium
- 2 - high

**users** - user mapping. From claim configured in _username_attribute_
to the local account name

**MFA** - under the **oauth** block, via setting `"require_mfa": true`,
the module will modify the requests to ask user to perform the MFA.
For more info on the exact form, see the `config_template.json` file.
- `qr` QR code encodes the authentication URL.
- `show`: show (`true`, default) or hide (`false`) the QR code
- `error_correction_level`: allowed correction levels are
- 0 - low
- 1 - medium
- 2 - high
- `users` User mapping from claim configured in _username_attribute_
to the local account name.
- `oauth` configuration for the OIDC identity provider.
- `require_mfa`: if `true` the module will modify the requests to ask
user to perform the MFA.

### Example Configuration for sshd

Expand Down
12 changes: 5 additions & 7 deletions config_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
"secret": "client_secret"
},
"scope": "openid profile",
"device_endpoint":"https://provider.com/devicecode",
"device_endpoint": "https://provider.com/devicecode",
"token_endpoint": "https://provider.com/token",
"userinfo_endpoint": "https://provider.com/userinfo",
"username_attribute": "preferred_username",
"require_mfa": false
},
"ldap": {
"hosts":
[
"hosts": [
"ldaps://ldap-server1:636",
"ldaps://ldap-server2:636",
"ldaps://ldap-server3:636"
Expand All @@ -25,16 +24,15 @@
"attr": "uid"
},
"qr": {
"show": true,
"error_correction_level": 0
},
"users": {
"provider_user_id_1":
[
"provider_user_id_1": [
"root",
"bob"
],
"provider_user_id_2":
[
"provider_user_id_2": [
"mike"
]
}
Expand Down
2 changes: 2 additions & 0 deletions src/include/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ void Config::load(const char *path) {
j.at("oauth").at("username_attribute").get<std::string>();
qr_error_correction_level =
j.at("qr").at("error_correction_level").get<int>();
qr_show =
(j["qr"].contains("show")) ? j.at("qr").at("show").get<bool>() : true;
if (j.find("ldap") != j.end() && j["ldap"].find("hosts") != j["ldap"].end()) {
for (auto &host : j["ldap"]["hosts"]) {
ldap_hosts.insert((std::string)host);
Expand Down
2 changes: 1 addition & 1 deletion src/include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Config {
std::string client_id, client_secret, scope, device_endpoint, token_endpoint,
userinfo_endpoint, username_attribute, ldap_basedn, ldap_user,
ldap_passwd, ldap_filter, ldap_attr;
bool request_mfa;
bool request_mfa, qr_show;
std::set<std::string> ldap_hosts;
int qr_error_correction_level;
std::map<std::string, std::set<std::string>> usermap;
Expand Down
41 changes: 24 additions & 17 deletions src/pam_oauth2_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,26 +80,32 @@ std::string getQr(const char *text, const int ecc = 0, const int border = 1) {
return oss.str();
}

std::string DeviceAuthResponse::get_prompt(const int qr_ecc = 0) {
std::string DeviceAuthResponse::get_prompt(const int qr_ecc = 0,
const bool qr_show = true) {
bool complete_url = !verification_uri_complete.empty();
std::string prompt_uri(complete_url ? verification_uri_complete
: verification_uri);
std::ostringstream prompt;
prompt << "Authenticate at\n-----------------\n"
<< std::regex_replace(prompt_uri, std::regex("\\s"), "%20")
<< "\n-----------------\n";
if (!complete_url) {
prompt << "With code" << user_code << user_code << "\n-----------------\n";
}

prompt << "Or scan the QR code to authenticate with a mobile device"
<< std::endl
prompt << "Authenticate at the identity provider using the following URL."
<< std::endl
<< getQr((complete_url ? verification_uri_complete : verification_uri)
<< std::endl;
if (qr_show) {
prompt << "Alternatively, to authenticate with a mobile device, scan the "
"QR code."
<< std::endl
<< std::endl
<< getQr(
(complete_url ? verification_uri_complete : verification_uri)
.c_str(),
qr_ecc)
<< std::endl
<< "Hit enter when you authenticate\n";
<< std::endl;
}
prompt << std::regex_replace(prompt_uri, std::regex("\\s"), "%20")
<< std::endl;
if (!complete_url) {
prompt << "With code: " << user_code << std::endl;
}
prompt << std::endl << "Hit enter when you have authenticated." << std::endl;
return prompt.str();
}

Expand Down Expand Up @@ -262,8 +268,8 @@ void get_userinfo(const char *userinfo_endpoint, const char *token,
}
}

void show_prompt(pam_handle_t *pamh, int qr_error_correction_level,
DeviceAuthResponse *device_auth_response) {
void show_prompt(pam_handle_t *pamh, const int qr_error_correction_level,
const bool qr_show, DeviceAuthResponse *device_auth_response) {
int pam_err;
char *response;
struct pam_conv *conv;
Expand All @@ -277,7 +283,7 @@ void show_prompt(pam_handle_t *pamh, int qr_error_correction_level,
syslog(LOG_ERR, "show_prompt: pam_get_item failed, rc=%d", pam_err);
throw PamError();
}
prompt = device_auth_response->get_prompt(qr_error_correction_level);
prompt = device_auth_response->get_prompt(qr_error_correction_level, qr_show);
msg.msg_style = PAM_PROMPT_ECHO_OFF;
msg.msg = prompt.c_str();
msgp = &msg;
Expand Down Expand Up @@ -389,7 +395,8 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
config.client_id.c_str(), config.client_secret.c_str(),
config.scope.c_str(), config.device_endpoint.c_str(),
config.request_mfa, &device_auth_response);
show_prompt(pamh, config.qr_error_correction_level, &device_auth_response);
show_prompt(pamh, config.qr_error_correction_level, config.qr_show,
&device_auth_response);
poll_for_token(config.client_id.c_str(), config.client_secret.c_str(),
config.token_endpoint.c_str(),
device_auth_response.device_code.c_str(), &token);
Expand Down
2 changes: 1 addition & 1 deletion src/pam_oauth2_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class DeviceAuthResponse {
public:
std::string user_code, verification_uri, verification_uri_complete,
device_code;
std::string get_prompt(const int qr_ecc);
std::string get_prompt(const int qr_ecc, const bool qr_show);
};

void make_authorization_request(const char *client_id,
Expand Down

0 comments on commit 9ff1824

Please sign in to comment.