githubAuthCallback is called after a user authorizes github app on their account It's implemented as a non-gRPC endpoint mounted directly on /github/auth/callback.
(w http.ResponseWriter, r *http.Request)
| 784 | // githubAuthCallback is called after a user authorizes github app on their account |
| 785 | // It's implemented as a non-gRPC endpoint mounted directly on /github/auth/callback. |
| 786 | func (s *Server) githubAuthCallback(w http.ResponseWriter, r *http.Request) { |
| 787 | ctx := r.Context() |
| 788 | claims := auth.GetClaims(r.Context()) |
| 789 | if claims.OwnerType() != auth.OwnerTypeUser { |
| 790 | http.Error(w, "unidentified user", http.StatusUnauthorized) |
| 791 | return |
| 792 | } |
| 793 | |
| 794 | // Get auth cookie |
| 795 | sess := s.cookies.Get(r, githubcookieName) |
| 796 | // Check that random state matches (for CSRF protection) |
| 797 | qry := r.URL.Query() |
| 798 | if qry.Get("state") != sess.Values[githubcookieFieldState] { |
| 799 | http.Error(w, "invalid state parameter", http.StatusBadRequest) |
| 800 | return |
| 801 | } |
| 802 | delete(sess.Values, githubcookieFieldState) |
| 803 | |
| 804 | // verify user's identity with github |
| 805 | code := qry.Get("code") |
| 806 | if code == "" { |
| 807 | http.Error(w, "unauthorised user", http.StatusUnauthorized) |
| 808 | return |
| 809 | } |
| 810 | |
| 811 | // exchange code to get an auth token and create a github client with user auth |
| 812 | c, ghToken, err := s.userAuthGithubClient(ctx, code) |
| 813 | if err != nil { |
| 814 | // todo :: check for unauthorised user error |
| 815 | http.Error(w, fmt.Sprintf("internal error %s", err.Error()), http.StatusInternalServerError) |
| 816 | return |
| 817 | } |
| 818 | |
| 819 | gitUser, _, err := c.Users.Get(ctx, "") |
| 820 | if err != nil { |
| 821 | // todo :: check for unauthorised user error |
| 822 | http.Error(w, fmt.Sprintf("internal error %s", err.Error()), http.StatusInternalServerError) |
| 823 | return |
| 824 | } |
| 825 | |
| 826 | // save the github user name |
| 827 | user, err := s.admin.DB.FindUser(ctx, claims.OwnerID()) |
| 828 | if err != nil { |
| 829 | // can this happen ?? |
| 830 | if errors.Is(err, database.ErrNotFound) { |
| 831 | http.Error(w, "unidentified user", http.StatusUnauthorized) |
| 832 | return |
| 833 | } |
| 834 | http.Error(w, fmt.Sprintf("internal error %s", err.Error()), http.StatusInternalServerError) |
| 835 | return |
| 836 | } |
| 837 | |
| 838 | _, err = s.admin.DB.UpdateUser(ctx, user.ID, &database.UpdateUserOptions{ |
| 839 | DisplayName: user.DisplayName, |
| 840 | PhotoURL: user.PhotoURL, |
| 841 | GithubUsername: gitUser.GetLogin(), |
| 842 | GithubRefreshToken: ghToken.RefreshToken, |
| 843 | GithubToken: ghToken.AccessToken, |
nothing calls this directly
no test coverage detected