@Summary OAuth 2.0 GitHub Callback @ID oauth-20-github-callback @Security CoderSessionToken @Tags Users @Success 307 @Router /api/v2/users/oauth2/github/callback [get]
(rw http.ResponseWriter, r *http.Request)
| 880 | // @Success 307 |
| 881 | // @Router /api/v2/users/oauth2/github/callback [get] |
| 882 | func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) { |
| 883 | var ( |
| 884 | // userOAuth2Github is a system function. |
| 885 | //nolint:gocritic |
| 886 | ctx = dbauthz.AsSystemRestricted(r.Context()) |
| 887 | state = httpmw.OAuth2(r) |
| 888 | auditor = api.Auditor.Load() |
| 889 | aReq, commitAudit = audit.InitRequest[database.APIKey](rw, &audit.RequestParams{ |
| 890 | Audit: *auditor, |
| 891 | Log: api.Logger, |
| 892 | Request: r, |
| 893 | Action: database.AuditActionLogin, |
| 894 | }) |
| 895 | ) |
| 896 | aReq.Old = database.APIKey{} |
| 897 | defer commitAudit() |
| 898 | |
| 899 | oauthClient := oauth2.NewClient(ctx, oauth2.StaticTokenSource(state.Token)) |
| 900 | |
| 901 | logger := api.Logger.Named(userAuthLoggerName) |
| 902 | |
| 903 | var selectedMemberships []*github.Membership |
| 904 | var organizationNames []string |
| 905 | redirect := state.Redirect |
| 906 | if !api.GithubOAuth2Config.AllowEveryone { |
| 907 | memberships, err := api.GithubOAuth2Config.ListOrganizationMemberships(ctx, oauthClient) |
| 908 | if err != nil { |
| 909 | logger.Error(ctx, "unable to list organization members", slog.Error(err)) |
| 910 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 911 | Message: "Internal error fetching authenticated Github user organizations.", |
| 912 | Detail: err.Error(), |
| 913 | }) |
| 914 | return |
| 915 | } |
| 916 | |
| 917 | for _, membership := range memberships { |
| 918 | if membership.GetState() != "active" { |
| 919 | continue |
| 920 | } |
| 921 | for _, allowed := range api.GithubOAuth2Config.AllowOrganizations { |
| 922 | if *membership.Organization.Login != allowed { |
| 923 | continue |
| 924 | } |
| 925 | selectedMemberships = append(selectedMemberships, membership) |
| 926 | organizationNames = append(organizationNames, membership.Organization.GetLogin()) |
| 927 | break |
| 928 | } |
| 929 | } |
| 930 | if len(selectedMemberships) == 0 { |
| 931 | status := http.StatusUnauthorized |
| 932 | msg := "You aren't a member of the authorized Github organizations!" |
| 933 | if api.GithubOAuth2Config.DeviceFlowEnabled { |
| 934 | // In the device flow, the error is rendered client-side. |
| 935 | httpapi.Write(ctx, rw, status, codersdk.Response{ |
| 936 | Message: "Unauthorized", |
| 937 | Detail: msg, |
| 938 | }) |
| 939 | } else { |
nothing calls this directly
no test coverage detected