Search

No Breached Passwords!




Here we have a demo of an Oauth app powered by Okta that prevents users with breached passwords from logging in?


So how does it work?


Just three easy steps


  1. Sign In widget that sends credentials to our server side that checks if the user's password has been compromised.


  var signIn = new OktaSignIn({
    baseUrl: '{{your okta url}}',
    features: {                        // Leave this set to true for the API demo
        registration: false,                   // Enable self-service registration flow
        rememberMe: true,                      // Setting to false will remove the checkbox to save username
        smsRecovery: true                   // Enable SMS-based account recover                // Enable voice call-based account recovery
    },
    processCreds: function (creds) {
      console.log(creds)
      var data = JSON.stringify({
      "username": creds.username,
      "password": creds.password
    });
      var settings = {
        "async": false,
        "crossDomain": true,
        "url": "https://{{our server }}/breachedPassword",
        "method": "POST",
        "headers": {
          "Content-Type": "application/json",
          "cache-control": "no-cache"
        },
        "processData": false,
        "data": data
      }

      $.ajax(settings).done(function (response) {
        console.log(response);
      });
    }
  });

2. Call the server side and check if the user's password has been breached using the haveibeenpwned api: https://haveibeenpwned.com/API/v3. If the user has been breached we update the Okta user profile with breachedPassword = true.



app.post("/breachedPassword", async (req, res) => {
  var username = req.body.username;
  const hash = crypto
    .createHash("sha1")
    .update(req.body.password)
    .digest("hex");
  var prefix = hash.slice(0, 5);
  var suffix = hash.split(prefix)[1];
  await axios
    .get("https://api.pwnedpasswords.com/range/" + prefix)
    .then(function(response) {
      var hashes = response.data.split("\n");
      var newHashes = hashes.map(function(item) {
        return item.split(":")[0];
      });
      var passwordIsBreached = newHashes.includes(suffix.toUpperCase());
        client.getUser(username).then(async user => {
          console.log(user);
          user.profile.breachedPassword = passwordIsBreached
          user
            .update()
            .then(user => {
              console.log(user);
              res.send({ data: passwordIsBreached });
            })
            .catch(function(error) {
              res.send({ data: passwordIsBreached });
            });
        });
        res.send({ data: passwordIsBreached });
    })
    .catch(function(error) {
      console.log(error);
        res.end();
    });
});

3. Finally using an inline token Hook from preventing a token from being minted to the app if the user's password is breached.



app.post("/", function(request, response) {
  console.log(request.body.data.context.user.passwordChanged);
  var lastPasswordChanged = request.body.data.context.user.passwordChanged;
  console.log("##############");
  console.log(request.body.data.access);
  var claims = request.body.data.access.claims;
  if (claims.breachedPassword) {
    var res = {
      error: {
        errorSummary: "Oh no your password has been breached",
        errorCauses: [
          {
            errorSummary: "breached pw!!",
            reason: "BREACHED_PASSWORD",
            locationType: "request",
            location: "data.userProfile.breachedPassword",
            domain: "external-service"
          }
        ]
      }
    };
    response.send(res);
  } else {
    var res = {
      commands: []
    };
    response.send(res);
  }
});

And that's it! Happy coding.



89 views0 comments

Recent Posts

See All