title: Golang Azure Active directory Token response was 401 unauthorized
body: <p>Have my client id and secret correct. My redirect url is - http://localhost:8080/callback . I have allowed public client flows in my AD. But everytime i execute the code main.go i get the error  Handler error: token response was 401 Unauthorized. So i do get the login page but whenever i click login it does authenticate me using my email id and password. But once i enter the redirect, i get the error  Handler error: token response was 401 Unauthorized.</p>
  <pre><code>package main
  
  import (
      &quot;crypto/sha256&quot;
      &quot;encoding/base64&quot;
      &quot;encoding/gob&quot;
      &quot;encoding/json&quot;
      &quot;fmt&quot;
      &quot;html/template&quot;
      &quot;log&quot;
      &quot;net/http&quot;
      &quot;net/url&quot;
      &quot;strings&quot;
  
      &quot;github.com/davecgh/go-spew/spew&quot;
      &quot;github.com/gorilla/sessions&quot;
  
      _ &quot;golang.org/x/net/context&quot;
      &quot;golang.org/x/oauth2&quot;
  )
  
  const (
      redirectURI string = &quot;http://localhost:8080/callback&quot;
  )
  
  // Authentication + Encryption key pairs
  var sessionStoreKeyPairs = [][]byte{
      []byte(&quot;something-very-secret&quot;),
      nil,
  }
  
  var store sessions.Store
  
  var (
      clientID string
      config   *oauth2.Config
  )
  
  type User struct {
      Email       string
      DisplayName string
  }
  
  func init() {
      // Create file system store with no size limit
      fsStore := sessions.NewFilesystemStore(&quot;&quot;, sessionStoreKeyPairs...)
      fsStore.MaxLength(0)
      store = fsStore
  
      gob.Register(&amp;User{})
      gob.Register(&amp;oauth2.Token{})
  }
  
  func main() {
      log.SetFlags(log.LstdFlags | log.Llongfile)
  
      clientID = &quot;&lt;client-id&gt;&quot;
      if clientID == &quot;&quot; {
          log.Fatal(&quot;AZURE_AD_CLIENT_ID must be set.&quot;)
      }
  
      config = &amp;oauth2.Config{
          ClientID:     clientID,
          ClientSecret: &quot;&lt;secret-id&gt;&quot;, // no client secret
          RedirectURL:  redirectURI,
  
          Endpoint: oauth2.Endpoint{
              AuthURL:  &quot;https://login.microsoftonline.com/&lt;Tenant-id&gt;/oauth2/authorize&quot;,
              TokenURL: &quot;https://login.microsoftonline.com/&lt;tenant-id&gt;/oauth2/token&quot;,
          },
  
          Scopes: []string{&quot;User.Read&quot;},
      }
  
      http.Handle(&quot;/&quot;, handle(IndexHandler))
      http.Handle(&quot;/callback&quot;, handle(CallbackHandler))
  
      log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
  }
  
  type handle func(w http.ResponseWriter, req *http.Request) error
  
  func (h handle) ServeHTTP(w http.ResponseWriter, req *http.Request) {
      defer func() {
          if r := recover(); r != nil {
              log.Printf(&quot;Handler panic: %v&quot;, r)
          }
      }()
      if err := h(w, req); err != nil {
          log.Printf(&quot;Handler error: %v&quot;, err)
  
          if httpErr, ok := err.(Error); ok {
              http.Error(w, httpErr.Message, httpErr.Code)
          }
      }
  }
  
  type Error struct {
      Code    int
      Message string
  }
  
  func (e Error) Error() string {
      if e.Message == &quot;&quot; {
          e.Message = http.StatusText(e.Code)
      }
      return fmt.Sprintf(&quot;%d: %s&quot;, e.Code, e.Message)
  }
  
  func IndexHandler(w http.ResponseWriter, req *http.Request) error {
      session, _ := store.Get(req, &quot;session&quot;)
  
      var token *oauth2.Token
      if req.FormValue(&quot;logout&quot;) != &quot;&quot; {
          session.Values[&quot;token&quot;] = nil
          sessions.Save(req, w)
      } else {
          if v, ok := session.Values[&quot;token&quot;]; ok {
              token = v.(*oauth2.Token)
          }
      }
  
      var data = struct {
          Token   *oauth2.Token
          AuthURL string
      }{
          Token:   token,
          AuthURL: config.AuthCodeURL(SessionState(session), oauth2.AccessTypeOnline),
      }
  
      return indexTempl.Execute(w, &amp;data)
  }
  
  var indexTempl = template.Must(template.New(&quot;&quot;).Parse(`&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;title&gt;Azure AD OAuth2 Example&lt;/title&gt;
  
      &lt;link href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot; integrity=&quot;sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u&quot; crossorigin=&quot;anonymous&quot;&gt;
    &lt;/head&gt;
    &lt;body class=&quot;container-fluid&quot;&gt;
      &lt;div class=&quot;row&quot;&gt;
        &lt;div class=&quot;col-xs-4 col-xs-offset-4&quot;&gt;
          &lt;h1&gt;Azure AD OAuth2 Example&lt;/h1&gt;
  {{with .Token}}
          &lt;div id=&quot;displayName&quot;&gt;&lt;/div&gt;
          &lt;a href=&quot;/?logout=true&quot;&gt;Logout&lt;/a&gt;
  {{else}}
          &lt;a href=&quot;{{$.AuthURL}}&quot;&gt;Login&lt;/a&gt;
  {{end}}
        &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;script src=&quot;https://code.jquery.com/jquery-3.2.1.min.js&quot; integrity=&quot;sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=&quot; crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
      &lt;script&gt;
  {{with .Token}}
        var token = {{.}};
  
        $.ajax({
          url: 'https://graph.microsoft.com/v1.0/me',
          dataType: 'json',
          success: function(data, status) {
              $('#displayName').text('Welcome ' + data.displayName);
          },
          beforeSend: function(xhr, settings) {
            xhr.setRequestHeader('Authorization', 'Bearer ' + token.access_token);
          }
        });
  {{end}}
      &lt;/script&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  `))
  
  func CallbackHandler(w http.ResponseWriter, req *http.Request) error {
      session, _ := store.Get(req, &quot;session&quot;)
  
      if req.FormValue(&quot;state&quot;) != SessionState(session) {
          return Error{http.StatusBadRequest, &quot;invalid callback state&quot;}
      }
  
      form := url.Values{}
      form.Set(&quot;grant_type&quot;, &quot;authorization_code&quot;)
      form.Set(&quot;client_id&quot;, clientID)
      form.Set(&quot;response_type&quot;, &quot;code&quot;)
      form.Set(&quot;scope&quot;, &quot;offline_access%20user.read&quot;)
      form.Set(&quot;redirect_uri&quot;, &quot;http%3A%2F%2Flocalhost%3A8080%2Fcallback&quot;)
      form.Set(&quot;response_mode&quot;, &quot;query&quot;)
      form.Set(&quot;state&quot;, &quot;12345&quot;)
  
      tokenReq, err := http.NewRequest(http.MethodPost, config.Endpoint.TokenURL, strings.NewReader(form.Encode()))
      if err != nil {
          return fmt.Errorf(&quot;error creating token request: %v&quot;, err)
      }
      tokenReq.Header.Set(&quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot;)
  
      resp, err := http.DefaultClient.Do(tokenReq)
      if err != nil {
          return fmt.Errorf(&quot;error performing token request: %v&quot;, err)
      }
      defer resp.Body.Close()
  
      if resp.StatusCode &gt;= 400 {
          return fmt.Errorf(&quot;token response was %s&quot;, resp.Status)
      }
  
      var token oauth2.Token
      if err := json.NewDecoder(resp.Body).Decode(&amp;token); err != nil {
          return fmt.Errorf(&quot;error decoding JSON response: %v&quot;, err)
      }
  
      session.Values[&quot;token&quot;] = &amp;token
      if err := sessions.Save(req, w); err != nil {
          return fmt.Errorf(&quot;error saving session: %v&quot;, err)
      }
  
      http.Redirect(w, req, &quot;/&quot;, http.StatusFound)
      return nil
  }
  
  func SessionState(session *sessions.Session) string {
      return base64.StdEncoding.EncodeToString(sha256.New().Sum([]byte(session.ID)))
  }
  
  func dump(v interface{}) {
      spew.Dump(v)
  }
  </code></pre>
  <p><a href="https://i.stack.imgur.com/9Cgkd.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9Cgkd.png" alt="After clicking login" /></a>
  <a href="https://i.stack.imgur.com/XVdFx.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XVdFx.png" alt="headers sent" /></a></p>