Vonageとは?
VonageはコミュニケーションAPIを提供している企業で、かなり簡単にSMSや電話での二段階認証や、コミュニケーションシステムの構築ができるサービスを提供しています。
今回、2023年アドベントカレンダーにてこのVonageが目に入ったのでちょっと記事を書いてみようかなと思いました。
メイン茶番(?)
登場人物
- 主人公: 悠斗
- ヒロイン: 美咲
プロローグ
俺は今日、ずっと好きだったの美咲の家で遊ぶことになった。
幾度となく想像してきたこの瞬間が、ついに目の前に広がろうとしていた。
「俺は今日...美咲の家で、告白をする!」
そう決めた俺は、美咲の家に向かった。
美咲の家
美咲「あれ、悠斗早かったね!」
悠斗「楽しみでちょっと早く来ちゃってさ」
美咲「とりあえず上がってよ」
美咲の家に入ると、親がいる様子はなかった。
美咲「今日は親いないから部屋であそぼっか」
悠斗「う、うん」
美咲は俺の手を引いて、部屋に連れて行った。
そこに広がっていたのは...
美咲の部屋に入った俺は、そこに広がっていたものに驚きを隠せなかった。
まるでストリーマーのようなセットが整えられていたのだ。
白いケースのゲーミングパソコンに、整理整頓されたデスクトップ。
他にもいろいろ配信する用の機材のようなものが部屋にはおかれていた。
悠斗「すごいねこれ」
美咲「うん、最近配信を始めててさ。意外とみんなが見てくれてうれしいんだよね」
悠斗「そうなんだ、今度俺にもチャンネル教えてよ」
美咲「もっと有名になったらねっ」
美咲「あ、ちょっと飲み物持ってくるね。お茶でいい?」
悠斗「うん、ありがとう」
美咲「じゃあちょっと待ってて」
美咲「あ、パソコンは勝手に触っちゃダメだよ~? 特にChromeはね?」
悠斗「あぁもちろん」
そそられる興味
美咲は部屋を出ていった。
...
いやこれはもう開くしかないだろ。
「特にChromeはね?」 とか言われたらChromeを開きたくなってしまう。
悠斗「これが美咲のChrome...」
やってはいけないことはわかっている。
だが...開いてしまえ!
カチッカチッ
ん?
に、認証プロセス?
認証コードを入れろ???
わからん!
だがとりあえずコードを入れるしかないっ...!
か、管理者に不正アクセスの通知を送信しました。 だってぇ!?
そのころ美咲は...
- 原文
Authentication of CHROME failed.
If this was not done by you, someone may have attempted to access your application illegally.
- 日本語訳
CHROME の認証に失敗しました。
これがあなたによって行われなかった場合、誰かがあなたのアプリケーションに不正にアクセスしようとした可能性があります。
ふーん...悠斗はChromeを開いたのね。
やっぱり男はみんな同じなのね。
SMSで送られる認証コードを入れないとアプリケーションが開かないようにしよう
というわけで主題です。
なお、今回は2FAと称していますが2FじゃねぇしあんまAじゃねぇ、なんかよくわからん認証システムってだけです。
VONAGE APIsからSMSを送信しよう
今回はVonageのアカウント作成などは割愛します。
Vonageのダッシュボードから「はじめに」>「SMS を送信」を選んでみましょう。
物は試しでSend message
を押してみましょう。
そうするとこんな風に、ご自身のアカウントの電話番号にSMSが送られてくると思います。
サンプルコードをもとに、自由にSMSを送るコードを書いてみよう
まずvonage
のインストールが必要です。
pip install vonage
でインストールできます。
import vonage
client = vonage.Client(key="API_KEY", secret="API_SECRET")
sms = vonage.Sms(client)
def send_sms(from_name: str, send_to: str, message: str)
return sms.send_message(
{
"from": from_name,
"to": send_to,
"text": message,
}
)
def main():
res = send_sms("Vonage APIs", "YOUR_PHONE_NUMBER", "Hello, World!")
if res["messages"][0]["status"] == "0":
print("Message sent successfully.")
else:
print(f"Message failed with error: {res['messages'][0]['error-text']}")
if __name__ == "__main__":
main()
サンプルコードをもとにこんなコードを書いてみました。
これを実行すると、YOUR_PHONE_NUMBER
にSMSが送られてくると思います。
あとはこれをもとに、認証コード風のコードを発行するコードを書いてみましょう。
認証コード発行まで
import random
import vonage
client = vonage.Client(key="API_KEY", secret="API_SECRET")
sms = vonage.Sms(client)
def send_sms(from_name: str, send_to: str, message: str)
return sms.send_message(
{
"from": from_name,
"to": send_to,
"text": message,
}
)
def main():
code = random.randint(0, 999999)
res = send_sms("Vonage APIs", "YOUR_PHONE_NUMBER", f"Your code is {code}.")
if res["messages"][0]["status"] == "0":
check_code = input("Please enter the code: ")
if int(check_code) == code:
print("Success!")
else:
print("Failed!")
else:
print(f"Message failed with error: {res['messages'][0]['error-text']}")
if __name__ == "__main__":
main()
このコードを実行すると、0~999999
の間の数字がランダムに生成され、それがSMSで送られてきます。
その後、コンソールにコードを入力するように求められるので、SMSで送られてきたコードを入力してみましょう。
もし正しいコードを入力した場合はSuccess!
と表示されると思います。
あとはこれにアプリケーションを起動するコードを追加すれば...
import subprocess
import os
import sys
import vonage
import dotenv
import random
import enum
dotenv.load_dotenv()
client = vonage.Client(key=os.getenv("VONAGE_KEY"), secret=os.getenv("VONAGE_SECRET"))
sms = vonage.Sms(client)
USER_NUMBER = os.getenv("VONAGE_NUMBER")
MAX_COUNT = 3
class KickStatus(enum.Enum):
PENDING = enum.auto()
SUCCESS = enum.auto()
FAILED = enum.auto()
class Applications(enum.Enum):
CHROME = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
def send_sms(from_name: str, send_to: str, message: str):
return sms.send_message(
{
"from": from_name,
"to": send_to,
"text": message,
}
)
def main():
if USER_NUMBER is None:
print("あなたの電話番号がセットされていません。")
return
if len(sys.argv) < 2:
print("アプリケーションIDが指定されていません。")
return
APPLICATION_ID = sys.argv[1]
if APPLICATION_ID is None:
print("アプリケーションIDがセットされていません。")
return
if APPLICATION_ID not in Applications.__members__:
print("アプリケーションIDが不正です。")
return
application = Applications[APPLICATION_ID]
masked_number = "*******" + USER_NUMBER[-2:]
onetime_key = random.randint(0, 999999)
res = send_sms("App 2FA", USER_NUMBER, f"The authentication code to activate {APPLICATION_ID} is {onetime_key} .\nDo not share this code with others.")
if res["messages"][0]["status"] == "0":
print("認証プロセスを開始します...")
else:
print(f"恐れ入りますが、このアプリケーションは現在使用できません。\nSMS認証が正常に行えませんでした。\n{res['messages'][0]['error-text']}")
return
kick = KickStatus.PENDING
failed_count = 0
while kick == KickStatus.PENDING:
check_key = input(f"{masked_number}に送信した認証コードを入力してください: ")
if int(check_key) == onetime_key:
print("認証成功...")
kick = KickStatus.SUCCESS
else:
print(f"認証コードが違います。残り{MAX_COUNT - failed_count - 1}/{MAX_COUNT}回。")
failed_count += 1
if failed_count >= MAX_COUNT:
kick = KickStatus.FAILED
print("認証失敗...")
break
if kick == KickStatus.FAILED:
send_sms("App 2FA", USER_NUMBER, f"Authentication of {APPLICATION_ID} failed.\nIf this was not done by you, someone may have attempted to access your application illegally.")
print("認証に失敗したため、アプリケーションを終了します。\n管理者に不正アクセスの通知を送信しました。")
input("Press Enter to exit.")
return
else:
print("アプリケーションを起動します。")
subprocess.Popen(application.value, cwd="\\".join(application.value.split("\\")[:-1]))
if __name__ == "__main__":
main()
これで、ちゃんとSMSに送信されたコードを入力しないとアプリケーションが起動しないようなものを作ることができました。
ちなみに、SMSの送信の送信名(App 2FA
としているもの)は、文字数制限があります。多分11文字かな。
もし心配なら「Try the SMS API」の画面のTry it out
で入力してみてください。Send message
が押せるかどうかで文字数制限がわかると思います。
まとめ
今回はVonage APIのとっかかりとして、SMSでアプリの起動を制限するようなものを作ってみました。
認証コードを入力するというのは、今回はコンソールからの入力でしたが、もちろんGUIで入力するようなものも作れます。
ちゃんと作れば、セキュリティー意識が高そうなシステムでも構築できそうですね~
Vonageは、オムニチャンネルを容易に実装可能なAPIをグローバルで提供している会社です。世界中で多くの方が使っているPSTNの電話やSMSをAPIで組み込む事が可能です。電話やSMSのみならず、Videoや各種メッセージチャネルや二要素認証を提供しています。
(引用: 【Vonage】コミュニケーションAPIを使ってみよう、Vonageのことなら何でも共有しよう! by Vonage Advent Calendar 2023)
Vonageは無料でお試しもできるので、もし興味があればぜひ使ってみてください。
それでは、よい2FAライフを!
おまけ
美咲「もう、悠斗ったら...」
悠斗「ごめんごめん、つい...」
美咲「まっ、次からはちゃんと気を付けてよね?」
美咲「(プレゼントの検索履歴見られなくてよかった...)」
Happy End