github.com/dirkm/go-swagger@v0.19.0/examples/oauth2/restapi/implementation.go (about)

     1  package restapi
     2  
     3  // THIS CODE HAS NOT BEEN GENERATED
     4  
     5  import (
     6  	"fmt"
     7  	"io/ioutil"
     8  	"log"
     9  	"net/http"
    10  
    11  	oidc "github.com/coreos/go-oidc"
    12  	"github.com/go-openapi/runtime"
    13  	"github.com/go-openapi/runtime/middleware"
    14  	"golang.org/x/net/context"
    15  	"golang.org/x/oauth2"
    16  )
    17  
    18  var (
    19  	// state carries an internal token during the oauth2 workflow
    20  	// we just need a non empty initial value
    21  	state = "foobar" // Don't make this a global in production.
    22  
    23  	// the credentials for this API (adapt values when registering API)
    24  	clientID     = "" // <= enter registered API client ID here
    25  	clientSecret = "" // <= enter registered API client secret here
    26  
    27  	//  unused in this example: the signer of the delivered token
    28  	// issuer = "https://accounts.google.com"
    29  
    30  	// the Google login URL
    31  	authURL = "https://accounts.google.com/o/oauth2/v2/auth"
    32  
    33  	// the Google OAuth2 resource provider which delivers access tokens
    34  	/* #nosec */
    35  	tokenURL    = "https://www.googleapis.com/oauth2/v4/token"
    36  	userInfoURL = "https://www.googleapis.com/oauth2/v3/userinfo"
    37  
    38  	// our endpoint to be called back by the redirected client
    39  	callbackURL = "http://127.0.0.1:12345/api/auth/callback"
    40  
    41  	// the description of the OAuth2 flow
    42  	endpoint = oauth2.Endpoint{
    43  		AuthURL:  authURL,
    44  		TokenURL: tokenURL,
    45  	}
    46  
    47  	config = oauth2.Config{
    48  		ClientID:     clientID,
    49  		ClientSecret: clientSecret,
    50  		Endpoint:     endpoint,
    51  		RedirectURL:  callbackURL,
    52  		Scopes:       []string{oidc.ScopeOpenID, "profile", "email"},
    53  	}
    54  )
    55  
    56  func login(r *http.Request) middleware.Responder {
    57  	// implements the login with a redirection
    58  	return middleware.ResponderFunc(
    59  		func(w http.ResponseWriter, pr runtime.Producer) {
    60  			http.Redirect(w, r, config.AuthCodeURL(state), http.StatusFound)
    61  		})
    62  }
    63  
    64  func callback(r *http.Request) (string, error) {
    65  	// we expect the redirected client to call us back
    66  	// with 2 query params: state and code.
    67  	// We use directly the Request params here, since we did not
    68  	// bother to document these parameters in the spec.
    69  
    70  	if r.URL.Query().Get("state") != state {
    71  		log.Println("state did not match")
    72  		return "", fmt.Errorf("state did not match")
    73  	}
    74  
    75  	myClient := &http.Client{}
    76  
    77  	parentContext := context.Background()
    78  	ctx := oidc.ClientContext(parentContext, myClient)
    79  
    80  	authCode := r.URL.Query().Get("code")
    81  	log.Printf("Authorization code: %v\n", authCode)
    82  
    83  	// Exchange converts an authorization code into a token.
    84  	// Under the hood, the oauth2 client POST a request to do so
    85  	// at tokenURL, then redirects...
    86  	oauth2Token, err := config.Exchange(ctx, authCode)
    87  	if err != nil {
    88  		log.Println("failed to exchange token", err.Error())
    89  		return "", fmt.Errorf("failed to exchange token")
    90  	}
    91  
    92  	// the authorization server's returned token
    93  	log.Println("Raw token data:", oauth2Token)
    94  	return oauth2Token.AccessToken, nil
    95  }
    96  
    97  func authenticated(token string) (bool, error) {
    98  	// validates the token by sending a request at userInfoURL
    99  	bearToken := "Bearer " + token
   100  	req, err := http.NewRequest("GET", userInfoURL, nil)
   101  	if err != nil {
   102  		return false, fmt.Errorf("http request: %v", err)
   103  	}
   104  
   105  	req.Header.Add("Authorization", bearToken)
   106  
   107  	cli := &http.Client{}
   108  	resp, err := cli.Do(req)
   109  	if err != nil {
   110  		return false, fmt.Errorf("http request: %v", err)
   111  	}
   112  	defer resp.Body.Close()
   113  
   114  	_, err = ioutil.ReadAll(resp.Body)
   115  	if err != nil {
   116  		return false, fmt.Errorf("fail to get response: %v", err)
   117  	}
   118  	if resp.StatusCode != 200 {
   119  		return false, nil
   120  	}
   121  	return true, nil
   122  }