가입할 때 사용자가 적어 낸 이메일 주소가 정말 그 사람의 것인지는 그 자체로는 알 수 없다. 누구든 남의 주소를 적어 낼 수 있고, 존재하지 않는 주소를 넣을 수도 있다. 이메일 인증은 적어 낸 주소를 그 사람이 실제로 통제하고 있음을 확인하는 절차다. 주소의 소유가 아니라 통제, 곧 그 주소로 온 메일을 받아 볼 수 있는지를 확인하는 것이 이 절차의 본질이다.
이번 편은 이메일 인증이 무엇을 확인하려는 것인지, 확인용 링크나 코드가 어떻게 작동하는지, 그 값이 왜 한 번만 쓰이고 곧 만료되어야 하는지, 이메일 인증과 로그인이 어떻게 다른지, 그리고 이 절차에서 정보가 새어 나가지 않게 하려면 무엇을 조심해야 하는지를 다룬다. 간단해 보이는 절차이지만, 방어의 관점에서 보면 여러 위험을 겨냥한 장치들이 얽혀 있다.
무엇을 확인하는 절차인가
이메일 인증이 확인하는 것은 사용자가 그 주소로 온 메일을 받아 볼 수 있다는 사실이다. 서비스가 그 주소로 확인용 값을 보내고, 사용자가 그 값을 되돌려 주면, 그 사용자가 그 주소의 메일함에 접근할 수 있음이 증명된다. 주소를 적어 냈다는 것만으로는 알 수 없던 통제 사실을 이 왕복으로 확인하는 것이다.
이 확인이 필요한 이유는 여러 가지다. 우선 잘못 적은 주소를 걸러 낼 수 있다. 오타가 있거나 존재하지 않는 주소라면 확인용 값이 도달하지 못하므로, 그 주소로는 인증이 완료되지 않는다. 이로써 연락이 닿지 않는 주소로 계정이 만들어지는 것을 막는다.
더 중요한 이유는 남의 주소를 함부로 쓰지 못하게 하는 것이다. 누군가 남의 주소를 적어 계정을 만들려 해도, 그 주소로 온 확인용 값을 받아 볼 수 없으면 인증을 통과하지 못한다. 그래서 이메일 인증은 남의 주소를 도용해 계정을 만드는 것을 막고, 그 주소의 실제 주인만 그 주소로 계정을 쓸 수 있게 한다.
이메일 주소는 흔히 계정 복구의 통로로도 쓰이므로, 그 주소의 통제를 확인해 두는 것은 뒷날의 안전에도 걸린다. 비밀번호를 잊었을 때 그 주소로 복구 수단을 보내는 이상, 그 주소가 진짜 그 사람의 것임을 미리 확인해 두어야 복구 경로가 믿을 만해진다. 이메일 인증은 지금의 확인이자 뒷날 복구의 밑바탕이다.
확인용 값이 작동하는 방식
이메일 인증은 서비스가 그 주소로 확인용 값을 보내고 사용자가 그것을 되돌려 주는 방식으로 이루어진다. 이 값은 대개 특정 주소를 누르면 확인이 완료되는 링크의 형태이거나, 사용자가 화면에 옮겨 적는 짧은 코드의 형태다. 어느 형태든, 그 값을 받아 볼 수 있어야만 되돌려 줄 수 있다는 점이 핵심이다.
링크 형태에서는 확인용 값이 링크 안에 담긴다. 사용자가 그 링크를 누르면 값이 서비스로 돌아오고, 서비스는 그 값이 자신이 보낸 것과 일치하는지 확인해 인증을 완료한다. 사용자가 값을 직접 옮겨 적지 않아도 되어 편하지만, 링크가 메일 밖으로 새어 나가지 않도록 그 값의 관리에 주의해야 한다.
코드 형태에서는 짧은 값을 사용자가 화면에 옮겨 적는다. 이 방식은 링크를 누르기 어려운 환경에서 쓸모가 있고, 링크 형태보다 값이 짧은 대신 옮겨 적는 수고가 든다. 코드가 짧은 만큼 무작위로 맞혀 볼 여지가 생기므로, 시도 횟수를 제한하고 곧 만료되게 하는 방어가 함께 필요하다.
어느 형태든 확인용 값은 예측할 수 없어야 한다. 값을 짐작할 수 있으면, 메일을 받아 보지 않고도 값을 맞춰 인증을 통과할 수 있기 때문이다. 그래서 링크에 담기는 값은 충분히 길고 무작위여야 하고, 짧은 코드는 무작위성에 더해 시도 제한과 짧은 수명으로 그 약점을 메워야 한다.
한 번만 쓰이고 곧 만료되어야 하는 이유
확인용 값은 한 번만 쓸 수 있어야 한다. 인증이 완료되는 순간 그 값을 폐기해, 같은 값이 다시 쓰이지 못하게 한다. 값이 여러 번 통하면, 그 값이 어딘가에 남아 새어 나갔을 때 뒤늦게 악용될 수 있기 때문이다. 한 번 쓰고 버리는 성질이 값의 노출 위험을 크게 줄인다.
값에는 짧은 수명도 두어야 한다. 확인용 값이 오래 유효하면, 메일이 어딘가에 남아 있는 동안 계속 통하게 된다. 그래서 값을 보낸 뒤 일정 시간이 지나면 자동으로 만료되게 해, 그 시간이 지난 값은 더 이상 통하지 않게 한다. 수명이 짧을수록 새어 나간 값이 악용될 창이 좁아진다.
새 값을 보내면 이전 값을 무효로 하는 처리도 필요하다. 사용자가 확인 메일을 다시 요청하면 새 값이 발급되는데, 이때 이전 값이 그대로 살아 있으면 유효한 값이 여럿 떠도는 셈이 된다. 그래서 새 값을 낼 때 이전 값을 폐기해, 언제나 가장 최근에 보낸 값 하나만 통하게 유지한다.
값을 서버에 보관할 때는 원래 형태 그대로 두지 않는 편이 안전하다. 저장소가 새어 나가더라도 확인용 값이 그대로 드러나지 않도록, 되돌릴 수 없는 형태로 바꾸어 두고 되돌아온 값을 같은 방식으로 바꿔 대조한다. 확인용 값도 일종의 비밀이므로, 비밀번호를 다룰 때의 자세를 여기에도 적용하는 것이다.
이메일 인증과 로그인의 구분
이메일 인증은 로그인과 다른 절차다. 로그인은 매번 신원을 확인해 서비스에 들어오게 하는 반복되는 절차이고, 이메일 인증은 그 주소의 통제를 확인하는 대개 한 번의 절차다. 둘을 뒤섞으면 확인용 값을 로그인 수단처럼 오용하게 되어 위험이 생긴다.
확인용 값은 그 주소의 통제를 증명하는 용도로만 쓰여야 하고, 그것으로 로그인 상태를 곧바로 부여해서는 안 된다. 확인이 완료되면 그 사실만 기록하고, 서비스에 들어오는 것은 정해진 로그인 절차를 따르게 한다. 확인용 값이 로그인을 대신하면, 그 값이 새어 나갔을 때 계정 접근까지 함께 넘어갈 수 있다.
다만 특정 상황에서는 확인 링크를 눌러 곧바로 이어지는 흐름을 두기도 한다. 이 경우에도 그 흐름은 정해진 로그인 절차와 분리해 다루고, 확인용 값 자체가 지속되는 접근 권한이 되지 않도록 한다. 확인과 접근을 분리하는 원칙을 지키되, 편의를 위한 흐름은 그 위험을 따로 통제한다.
이메일 인증이 끝났다고 해서 그 주소가 영원히 그 사람의 것이라고 단정할 수도 없다. 주소는 뒷날 다른 사람에게 넘어갈 수 있고, 주인이 바뀔 수 있다. 그래서 중요한 동작 앞에서는 이메일 인증만으로 모든 것을 갈음하지 않고, 다른 확인 수단을 함께 두는 것이 안전하다.
정보 노출을 막는 처리
이메일 인증 절차에서 흔히 새어 나가는 정보가 특정 주소의 가입 여부다. 어떤 주소가 이미 가입되어 있는지 아닌지를 응답의 차이로 알 수 있으면, 그 정보가 다른 공격의 발판이 된다. 그래서 주소를 입력받아 처리할 때, 가입된 주소와 그렇지 않은 주소에 대한 응답을 겉으로 구분되지 않게 두는 것이 안전하다.
확인 메일을 보내는 요청도 빈도를 제한해야 한다. 같은 주소로 확인 메일을 무제한으로 보낼 수 있으면, 그 주소의 주인에게 대량의 메일을 쏟아붓는 데 악용될 수 있고 서비스의 발송 자원도 낭비된다. 그래서 짧은 시간에 같은 주소로 보내는 확인 메일의 수를 제한해, 이런 남용을 막는다.
짧은 코드 형태에서는 맞혀 보는 시도를 제한하는 것이 특히 중요하다. 코드가 짧으므로 여러 값을 던져 보면 우연히 맞을 수 있는데, 시도 횟수를 제한하고 일정 횟수를 넘으면 그 코드를 무효로 하면 이 위험이 줄어든다. 짧은 값의 편의를 취하는 대신 시도 제한으로 그 약점을 메우는 것이다.
확인 링크가 담긴 메일 자체도 새어 나갈 수 있음을 염두에 두어야 한다. 메일은 여러 곳을 거쳐 전달되고 오래 남을 수 있으므로, 그 안의 값이 노출될 가능성을 완전히 배제할 수 없다. 그래서 값을 한 번만 쓰이게 하고 짧게 만료시키는 방어가 여기서 힘을 발휘한다. 메일이 새어 나가더라도 그 안의 값이 이미 쓰였거나 만료되었다면 악용될 여지가 없다.
주소 변경과 재인증
사용자가 이메일 주소를 바꾸려 할 때도 인증이 필요하다. 새 주소로 바꾸는 것을 그대로 허용하면, 그 새 주소가 정말 그 사람의 것인지 확인되지 않은 채 계정의 연락 통로가 바뀌어 버린다. 그래서 주소를 바꿀 때는 새 주소로 확인용 값을 보내, 그 주소의 통제를 다시 확인한 뒤에 변경을 완료한다.
주소 변경은 계정 복구의 통로가 바뀌는 일이므로 특히 신중해야 한다. 이메일이 복구 수단으로 쓰이는 이상, 주소를 바꾸는 것은 그 계정의 마지막 방어선을 옮기는 것과 같다. 그래서 주소를 바꿀 때는 새 주소의 확인에 더해, 현재 로그인한 사용자가 진짜 주인임을 다시 확인하는 절차를 함께 두는 것이 안전하다.
주소가 바뀌었다는 사실은 이전 주소에도 알리는 것이 좋다. 만약 계정이 이미 도용되어 주소가 몰래 바뀌는 상황이라면, 이전 주소로 온 알림이 원래 주인에게 이상을 알아채게 하는 마지막 기회가 된다. 그래서 주소 변경 시 이전 주소로도 통지를 보내, 원래 주인이 대응할 여지를 남긴다.
변경이 완료되면 이전 주소로는 더 이상 계정을 확인하거나 복구할 수 없게 정리해야 한다. 이전 주소와 이어져 있던 확인 정보를 지워, 바뀐 뒤에 이전 주소로 엉뚱한 접근이 이루어지지 않게 한다. 주소를 잇는 일과 마찬가지로 끊는 일도 빠짐없이 정리해야 변경이 온전해진다.
미인증 상태를 다루기
이메일 인증을 도입하면, 가입은 했으나 아직 주소를 확인하지 않은 사용자가 생긴다. 이 미인증 상태를 어떻게 다룰지가 하나의 설계 지점이다. 확인을 마쳐야만 서비스를 쓸 수 있게 할지, 확인 전에도 일부는 쓰게 할지에 따라 사용자 경험과 방어의 균형이 달라진다.
확인을 완전히 마쳐야만 진입을 허용하면 방어는 확실하지만, 확인 메일이 늦게 도착하거나 놓친 사용자가 문턱에서 막힌다. 반대로 확인 전에도 자유롭게 쓰게 하면 진입은 매끄럽지만, 확인되지 않은 주소로 만들어진 계정이 쌓인다. 그래서 많은 서비스가 중간을 택해, 확인 전에는 기본적인 이용만 허용하고 중요한 동작은 확인 뒤로 미룬다.
미인증 상태에서 제한하는 동작은 위험의 크기로 정한다. 다른 사용자에게 영향을 주거나 되돌리기 어려운 동작, 이메일이 통로가 되는 복구와 얽힌 동작은 확인 뒤로 미루는 것이 안전하다. 반면 둘러보기처럼 위험이 낮은 동작은 확인 전에도 허용해 진입의 부담을 던다. 무엇을 미룰지의 기준을 위험에 두면 판단이 일관된다.
미인증 계정이 무한정 쌓이지 않도록 정리하는 절차도 필요하다. 확인되지 않은 채 오래 방치된 가입은 일정 기간이 지나면 정리하거나, 확인을 다시 안내한다. 이렇게 하면 존재하지 않는 주소나 남의 주소로 만들어진 계정이 저장소에 오래 남는 것을 막을 수 있다. 확인의 절차만큼이나 확인되지 않은 것의 처리도 함께 설계해야 한다.
확인 상태는 사용자에게도 분명히 보여 주는 것이 좋다. 지금 주소가 확인되었는지, 확인하지 않으면 무엇이 제한되는지를 명확히 알리면, 사용자가 확인을 미루다 곤란을 겪는 일이 줄어든다. 상태를 감추기보다 드러내어, 사용자가 스스로 확인을 마치도록 이끄는 것이 매끄러운 흐름을 만든다.
정리하면 이메일 인증은 적어 낸 주소를 사용자가 실제로 통제하고 있음을 확인하는 절차로, 예측 불가능하고 한 번만 쓰이며 곧 만료되는 확인용 값으로 이루어진다. 이 절차는 로그인과 구분되어야 하고, 가입 여부가 새어 나가지 않게 응답을 맞추며 발송과 시도를 제한해야 한다. 주소를 바꿀 때도 새 주소를 다시 확인하고 이전 주소에 반드시 알린다. 다음 편에서는 비밀번호 하나에만 기대지 않는 두 번째 인증 수단을 들여다본다.