Can't seem to figure out authentication (goth/gorilla sessions)

xuanbao · · 458 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>So I&#39;m trying to get an authentication system to work using <a href="https://github.com/markbates/goth" rel="nofollow">goth</a> and Auth0 as a provider.</p> <p>Most of what I have is pasted from the goth example:</p> <pre><code>router.Get(&#34;/auth/{provider}/callback&#34;, func(w http.ResponseWriter, r *http.Request) { user, err := gothic.CompleteUserAuth(w, r) if err != nil { fmt.Fprintln(w, err) return } t, _ := template.New(&#34;foo&#34;).Parse(userTemplate) session, err := gothic.Store.Get(r, &#34;auth0-gothic-session&#34;) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } session.Values[&#34;user&#34;] = user.UserID err = session.Save(r, w) if err != nil { fmt.Println(&#34;could not save session&#34;) } t.Execute(w, user) }) </code></pre> <p>This is the function that (I assume) does the main login/registering part. The URL is the Auth0 callback URL. That&#39;s the only time I get the <code>user</code> object with all the data that Auth0 provides me with. I think that goth doesn&#39;t do anything with that by default, so I suppose I have to put the user ID into the session/cookie to know who that session belongs to (<code>session.Values[&#34;user&#34;] = user.UserID</code>). Or is the user info automatically put into the session by goth?</p> <p><code>gothic.Store</code> is a <code>sessions.CookieStore btw.</code></p> <p>Then for other routes, I can check if the session cookie has a User ID in it:</p> <pre><code>if _, ok := session.Values[&#34;user&#34;].(string); !ok { w.Write([]byte(&#34;Not logged in&#34;)) //redirect or something return } </code></pre> <p>But then there&#39;s also this part in the example which I&#39;m not sure what it does:</p> <pre><code>router.Get(&#34;/auth/{provider}&#34;, func(w http.ResponseWriter, r *http.Request) { // try to get the user without re-authenticating if gothUser, err := gothic.CompleteUserAuth(w, r); err == nil { t, _ := template.New(&#34;foo&#34;).Parse(userTemplate) t.Execute(w, gothUser) } else { gothic.BeginAuthHandler(w, r) } }) </code></pre> <p>CompleteUserAuth is called again, but I thought you logged in with the other URL.</p> <p><del>Now to invalidate a session, I call <code>goth.Logout(w, r)</code>, but that doesn&#39;t seem to be doing anything, the session cookie is still in the browser and the check from above if the user is logged in will still evaluate as logged in. If I invalidate the cookie manually though with <code>session.Options.MaxAge = -1; session.Save(w, r)</code>, the user is logged out immediately upon refresh. Why is that since the logout function does exactly that?</del></p> <p>I&#39;ve read every bit of documentation I could find, but none of them included answers to my questions. My questions probably boil down to: What does goth do for me, and what do I have to take care of myself?</p> <p>Maybe I&#39;m missing something huge or not understanding a concept, please explain it to me! It don&#39;t want to do anything wrong with authentication.</p> <p>Thanks a lot!</p> <hr/>**评论:**<br/><br/>try2think1st: <pre><p>Read about OAuth authentication flow and you will see why you need two routes to complete the login process. Goth does the communication with the OAuth providers for you yielding the user&#39;s information. Your job is to handle this data in the callback get request, i.e. creating the session and maybe saving user data to a database if needed by your app.</p></pre>cube2222: <pre><p>Check out my blog post about oauth and oauth in go:</p> <p><a href="https://jacobmartins.com/2016/02/29/getting-started-with-oauth2-in-go/" rel="nofollow">https://jacobmartins.com/2016/02/29/getting-started-with-oauth2-in-go/</a></p></pre>nesigma: <pre><blockquote> <p>Note that the oauthStateString should be randomly generated on a per user basis.</p> </blockquote> <p>What is a good way to generate the state token on a per user basis?</p></pre>cube2222: <pre><p>generate a session for the user, stored in a cookie and in a database (or a map) (just a key being the cookie and the value being arbitrary data you can put there) </p> <p>-&gt;</p> <p>crypto.Read into a byte slice</p> <p>-&gt;</p> <p>urlencode/base32encode/base64encode</p> <p>-&gt;</p> <p>put into a map / database / redis into the session data for the current session</p> <p>-&gt;</p> <p>when the user comes back, get his session and check if the state string matches the one in your database/map/redis</p></pre>nesigma: <pre><p>Thanks for your reply</p> <blockquote> <p>when the user comes back, get his session and check if the state string matches the one in your database/map/redis</p> </blockquote> <p>I thought the state token was only useful to do the oauth login and so after the login is successful, it can be safely discarded. Why do I need to keep it in the database along with the session?</p></pre>cube2222: <pre><p>You should create the session even before the user authenticates. You create the session for the current visitor -&gt; add the state to the session -&gt; redirect him to login -&gt; when he comes back check if the session matches -&gt; you can delete the state from the session now.</p></pre>nesigma: <pre><blockquote> <p>You create the session for the current visitor -&gt; add the state to the session</p> </blockquote> <p>Why add the state to the session? What problem does it solve?</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

458 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传