<p>At work I primary use Ruby and rely on its frameworks. Now I'm working on a Go project and decided to write everything from scratch.</p>
<p>Please tell me if you see any security flaws in my auth implementation.</p>
<ol>
<li>an existing user creates an invitation by entering an email address</li>
<li>a unique code is generated and sent to this email</li>
<li>to accept the invitation the user has to click on the provided link: <a href="http://example.com/signup/abcd" rel="nofollow">http://example.com/signup/abcd</a></li>
<li>if the code is known and a valid username and password is provided</li>
<li>then a new user account is created and</li>
<li>the user gets signed in automatically</li>
</ol>
<p>SignupHandler:</p>
<pre><code>import "github.com/gorilla/sessions"
store = sessions.NewCookieStore([]byte(conf.SessionKey))
session, err := store.Get(r, config.SessionName)
session.Values["user_id"] = user.ID
session.Save(r, w)
http.Redirect(w, r, "/app", http.StatusFound)
</code></pre>
<p>Every subsequent request will be authenticated using a middleware:</p>
<pre><code>r.Handle("/app", auth.Middleware(appHandler)).Methods("GET")
</code></pre>
<p>This middleware works basically like this:</p>
<pre><code>session, err := authstore.Get(r, config.SessionName) // 403 if no session found
userID, found := session.Values["user_id"] // 403 if no user_id found
if userService.UserExists(userID.(int)) == false { // 403 if no user found
auth.store.MaxAge(maxAge) // renew session (1 week)
auth.store.Save(r, w, session)
// pass the user_id to the handler via context
ctx := context.WithValue(r.Context(), UserIDKey, userID)
next.ServeHTTP(w, r.WithContext(ctx))
</code></pre>
<p>One important thing I'm going to add is gorillatoolkit.org/pkg/csrf.</p>
<hr/>**评论:**<br/><br/>iroflmaowtf: <pre><blockquote>
<p>a unique code is generated and sent to this email</p>
</blockquote>
<p>triple check your uniqueness, better yet, add a unique constraint on the code field in the db;</p>
<p>while you're on this, ensure that it will be activated once</p>
<p>can the cookie be hijacked? i.e. you auth normally through the browser, and try to login in incognito, by copy-pasting the cookie</p></pre>wilhelmsburg: <pre><p>Why is uniqueness so important? A code is generated for one particular email address only. When the invitation is accepted by the invitee, then the code gets invalid. It can't be used twice or for another email address.</p>
<p>I generate a code like this:</p>
<pre><code>data := []byte(fmt.Sprintf("%s %d", secret, time.Now().UnixNano()))
return fmt.Sprintf("%x", md5.Sum(data))
</code></pre>
<p>The code is stored together with the invitee's email and only valid if AcceptedAt is nil.</p></pre>wilhelmsburg: <pre><p>Cookie hijacking is possible at the moment. I have to set the Secure and HttpOnly flags to prevent this. Thanks for the pointer, <a href="/u/iroflmaowtf" rel="nofollow">/u/iroflmaowtf</a> </p></pre>epiris: <pre><p>No one here can "check" the implementation for security holes without the implementation :) A bullet point list of common user registration UX and godoc style example of gorilla/sessions isn't really a implementation, if you post the code at some point I'll look though if you tag my user.</p></pre>wilhelmsburg: <pre><p><a href="/u/epiris" rel="nofollow">/u/epiris</a> You are absolutely right. I created a gist with the relevant parts:</p>
<p><a href="https://gist.github.com/kschaper/0efb060c671ea550976317f58c4afaab" rel="nofollow">https://gist.github.com/kschaper/0efb060c671ea550976317f58c4afaab</a></p>
<p>Please take a look.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传