@paradite answer covers your question fully, I would add that there are React libraries that handles that for you in the frontend: https://www.npmjs.com/package/@react-oauth/google or https://www.npmjs.com/package/react-social-login-buttons
It allows you to use a pre-made button, as simple as (in case of the first package)
<GoogleLogin
onSuccess={(resp) => { .. call your backend with resp .. })}
onError={(e) => { ... })}
/>
It really depends on your use-case; there are couple examples in the npm package site, and I used it lately in one of my projects and can say it simplifies the process.
On the backend, you need to decide which flow you gonna use: Signin (simpler) or Authorization (if you need extra scopes, access-tokens, refresh tokens, etc.)
The first is simpler since you get JWT which you decode and validate, and you have the user info.
If you want to implement the latter, have your backend get from the client the code
and your backend has to exchange that with the provider, something like this:
type UserData struct {
Email string
Name string
Token *oauth2.Token
}
var googleOauthConfig = &oauth2.Config{
RedirectURL: "http://localhost:1323/oauth/callback",
ClientID: "your-client-id.apps.googleusercontent.com",
ClientSecret: "your-secret",
Scopes: []string{"profile", "email"},
Endpoint: google.Endpoint,
}
func GetUserDataFromGoogle(code string) (UserData, error) {
// Use code to get token and get user info from Google.
var userData UserData
token, err := googleOauthConfig.Exchange(context.Background(), code)
if err != nil {
return userData, fmt.Errorf("code exchange wrong: %s", err.Error())
}
response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken)
if err != nil {
return userData, fmt.Errorf("failed getting user info: %s", err.Error())
}
defer response.Body.Close()
contents, err := io.ReadAll(response.Body)
if err != nil {
return userData, fmt.Errorf("failed read response: %s", err.Error())
}
err = json.Unmarshal(contents, &userData)
userData.Token = token
return userData, nil
}
The token includes access_token
, refresh_token
which you can use to fetch user information from the provider.
Note I'm using https://github.com/golang/oauth2 library here for the protocol implementation. In your handler you extract the code and call this function, if the code is valid you'll get the userData, otherwise you'll get an error.
This bypass the CORS issue, and and simplify the solution. I used Google in the example, but Oauth2 library supports many other providers.
b.com
or fromsso.example.com
? – Hectolitersso.example.com
– Aspiresso.example.com
does not allow cross origin requests and you don't have access to its server to modify the access controll then I'm not sure your react app will ever be able to access its resources. – Hectoliter