hectorm/otpauth

How to get time left (counter)

perry-mitchell opened this issue · 3 comments

Hi!

Some other OTP libraries provide counters which return the amount of seconds/time left of the current period. Is there some way to do this with otpauth? I'm not super familiar with how they work - Would you have some pointers as to how I could process the current period time left?

I'm using TOTP at the moment.

Hi, I created a quick example for you.

https://codesandbox.io/embed/counter-3v3ro

@hectorm This is great, thanks! I appreciate the fast reply.

Btw we'll be using your library in our password manager, Buttercup (Github) ✌️

It's always a pleasure to know that my work is useful to others.
I've checked your project and it seems awesome, keep up with the good work!

I leave here the content of the previous link for future references.
<template>
  <div class="totp">
    <h1>{{ token }}</h1>
    <progress :value="progress" :max="total"></progress>
    <h5>{{ uri }}</h5>
  </div>
</template>

<script>
import { TOTP, Secret } from "otpauth";

export default {
  name: "TOTP",
  props: {
    issuer: {
      type: String,
      default: ""
    },
    label: {
      type: String,
      default: ""
    },
    algorithm: {
      type: String,
      default: "SHA1"
    },
    digits: {
      type: Number,
      default: 6
    },
    period: {
      type: Number,
      default: 30
    },
    secret: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      token: "",
      progress: 0,
      total: 1000,
      timer: null
    };
  },
  computed: {
    totp() {
      return new TOTP({
        issuer: this.issuer,
        label: this.label,
        algorithm: this.algorithm,
        digits: this.digits,
        period: this.period,
        secret: Secret.fromB32(this.secret)
      });
    },
    uri() {
      return this.totp.toString();
    },
    running() {
      return this.timer !== null;
    }
  },
  methods: {
    start() {
      if (this.timer === null) {
        let progress;
        let period = this.period;
        let total = this.total;

        let tick = () => {
          progress = (total * (1 - (((0.001 * Date.now()) / period) % 1))) | 0;

          if (progress !== this.progress) {
            if (progress < this.progress) {
              this.token = this.totp.generate();
            }

            this.progress = progress;
          }

          this.timer = requestAnimationFrame(tick);
        };

        tick();
      }

      return this;
    },
    stop() {
      if (this.timer !== null) {
        cancelAnimationFrame(this.timer);
        this.timer = null;
      }

      return this;
    }
  },
  watch: {
    totp() {
      this.stop().start();
    }
  },
  created() {
    this.start();
  },
  beforeDestroy() {
    this.stop();
  }
};
</script>