GOLANG HTTP Basic-Auth with Google App Engine URLFetch - google-app-engine

How can I add an Authorization header to urlfetch client with Go?
There is a similar question answered for java and python, but not Go.

urlfetch.Client(ctx) returns an HTTP client (http://godoc.org/google.golang.org/appengine/urlfetch#Client)
The http.Client has methods for Get, Post, etc... It also has Do which you can hand an arbitrary request. Create a request using http.NewRequest:
req, err := http.NewRequest("GET", "http://www.google.com", nil)
Then you can add a header like this:
req.Header.Set("Authorization", "whatever")
And call Do:
res, err := client.Do(req)

I'm new to Go, please excuse this code for being ugly/malformed/just plain wrong.
I've been working my way though this and ran across the same problem on appengine.
#Caleb's answer above was a big help. I've just added some detail to that to help someone who might come across a similar problem.
Here's what my import statement looks like:
Import {
"appengine"
"appengine/urlfetch"
"bytes"
"encoding/json"
"fmt"
"golang.org/x/oauth2"
"io/ioutil"
"net/http"
"net/url"
}
This is a function that receives and incoming authentication callback request, then replies with a request for an access token from the authentication server. In this case, fitbit, which needs an Authentication header set to "Basic" with some extra information. I couldn't figure out how to do this with the stock Oauth2 library, which doesn't seem to easily allow changing the request headers.
As you can see we the context of the incoming request (r). From that context, we get the http.Client from urlfetch.
Then we pack up and send a request back, with some authorization information.
After we get a response we print the results to the browser.
Hope this helps!
func authCallbackHandler(w http.ResponseWriter, r *http.Request) {
data := url.Values{}
data.Set("client_id", "231343")
data.Add("grant_type", "authorization_code")
data.Add("redirect_uri", "http://localhost:8080/callmebacklaterok")
data.Add("code", "authcode123132")
encodedData := data.Encode()
c := appengine.NewContext(r)
client := urlfetch.Client(c)
urlStr := "https://api.fitbit.com/oauth2/token"
req, _ := http.NewRequest("POST", urlStr,bytes.NewBufferString(encodedData))
req.Header.Add("Authorization", "Basic RmFuY3kgbWVldGluZyB5b3UgaGVyZSEg")
resp, _ := client.Do(req)
defer resp.Body.Close()
fmt.Fprint(w, resp)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
}
var bodydata interface{}
err = json.Unmarshal(body, &bodydata)
if err != nil {
panic(err.Error())
}
fmt.Fprint(w, bodydata)
}

Related

Golang SQL Package not using defined database parameters

I'm trying to create a practice program where I accept API requests from a front end and then store data to a postgres database.
In the included code you can see that I define my parameters for connecting to the local database server, however when I run the Go program after starting the postgres server in my terminal, I get the error as included 'pq: database "root" does not exist'.
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
const (
host = "localhost"
port = 5432
user = "root"
password = ""
dbname = "postgres"
)
func ConnectDatabase() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
panic(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("Successfully connected!")
}
Image of the console containing the error
I'm quite new to this, but it doesn't really make sense to me as I'm directly specifiying which database to use (which is obviously not "root"). Could it somehow have something to do with postgres by default trying to access a database with the same name as my username. If so what is the point of specifying which databse I want to connect to?
Thanks for the help in advance.

Doing a post request on golang for uber authentication not working

I'm getting a 400 Bad Request when doing a request do oauth on uber API. I was successful in doing redirection. But when trying to do oauth, it fails. Here's how I've set up my code.
type UberRequest struct {
ClientSecret string `json:"client_secret"`
ClientId string `json:"client_id"`
GrantType string `json:"grant_type"`
RedirectURI string `json:"redirect_uri"`
Code string `json:"code"`
}
func HandlerUberAPI(w http.ResponseWriter, r *http.Request){
c := appengine.NewContext(r)
AuthorizationCode := r.URL.Query().Get("code")
client := urlfetch.Client(c)
uberRequestForm := &UberRequest{
ClientSecret: CLIENT_SECRET,
ClientId: CLIENT_ID,
GrantType: "authorization_code",
RedirectURI: URI_REDIRECT,
Code: CODE,
}
uberRequestFormJson, _ := json.Marshal(uberRequestForm)
req, _ := http.NewRequest("POST", UberTokenHost, strings.NewReader(string(uberRequestFormJson)))
req.Header.Set("Content-Type", "application/json")
}
Also, if you're interested in looking at the golang code via playground - here it is https://play.golang.org/p/o8EtgudiMR
I know that my client secret and other information works as I've tested in on postman, I don't know why it fails on google app engine.
The authorization and authentication documentation doesn't mention anything about JSON.
The request to the GET https://login.uber.com/oauth/v2/authorize
endpoint requires you to send the parameters in the query string of the URL using the GET HTTP method, not in the body of the HTTP request.
Make sure to URL/percent encode each parameter you are sending.

Include email header in app engine using go?

The google app engine documentation doesn't describe how to include an email header, how do you do it, i.e. How do you change this?
msg := &mail.Message{
Sender: "Example.com Support <support#example.com>",
To: []string{"email#bob.com"},
Subject: "Confirm your registration",
Body: fmt.Sprintf(confirmMessage, url),
}
if err := mail.Send(c, msg); err != nil {
c.Errorf("Couldn't send email: %v", err)
}
In the appengine/mail reference you can find that type Message has a field called Headers:
// Extra mail headers.
// See https://developers.google.com/appengine/docs/go/mail/overview
// for permissible headers.
Headers mail.Header
The type mail.Header can be found in the net/mail package, and only the following header names may be used, as described in the above overview link:
In-Reply-To
List-Id
List-Unsubscribe
On-Behalf-Of
References
Resent-Date
Resent-From
Resent-To
Example: (untested)
import netmail "net/mail" // mail is already taken by appengine/mail
...
msg := &mail.Message{
Sender: "Example.com Support <support#example.com>",
To: []string{"email#bob.com"},
Subject: "Confirm your registration",
Body: fmt.Sprintf(confirmMessage, url),
Headers: netmail.Header{"In-Reply-To": []string{"123456789"}},
}

How to properly add OAuth headers for a QuickBooks API call in Google Go

I am just trying to get a proof of concept working to test a connection to the QB api for a QB Online account. I have never tried to make an OAuth connection before like this, so I'm not sure that I am doing it right. Here's what I have so far, and it makes the request but I get a 401 error returned from QB's server (Unauthorized OAuth Token: signature_invalid401SERVER):
client := &http.Client{}
if req, err := http.NewRequest("GET", "https://qbo.intuit.com/qbo1/resource/customers/v2/717594130", nil); err != nil {
//handle error
} else {
req.Header.Add("Authorization", "OAuth oauth_token=\"MY_TOKEN\",oauth_nonce=\"7758caa9-e1f4-4fa1-84c5-5759fd513a88\",oauth_consumer_key=\"MY_KEY\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1369259523\",oauth_version=\"1.0\",oauth_signature=\"MY_SIG\"")
if resp, err := client.Do(req); err != nil {
//handle error
} else {
defer resp.Body.Close()
contents, err := ioutil.ReadAll(resp.Body)
if err != nil {
//handle error
}
myOutput := string(contents)
}
}
Could the problem may be with my settings on my QB account instead? There is a setting for "Host Name Domain" that I think it might only allow connections from what I have entered there (which is currently intuit.com). If that is the case, how do I set that to allow connections from my dev app on my localhost?
Are you using the correct OAuth algorithm to generate the signature?
Can you post an actual request/response that shows the outgoing signature/OAuth header, and the response you get back from Intuit?
Your code doesn't show any of that, and it doesn't look like you're using an Intuit DevKit, so that's probably the place to start. My guess would be that the signature you're sending isn't valid. I would highly recommend you find a OAuth library, and use that OAuth library, rather than try to roll your own OAuth algorithm.
As far as this goes:
Could the problem may be with my settings on my QB account instead?
There is a setting for "Host Name Domain" that I think it might only
allow connections from what I have entered there (which is currently
intuit.com).
That is not likely to be the problem... but to get any further than a simple test request, you will need to set that to your host name. If it's a local dev box, you can enter your local dev boxes hostname (e.g. http://localhost/ or http://192.168.1.2/ or anything like that is fine - whatever URL you use to hit your dev box)

Implementing OAuth2 Facebook login without http.Redirect

The following App Engine handler works to the extent that I can obtain a token:
func home(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
oaConfig := map [string]string {
"ClientID": "(redacted)",
"ClientSecret": "(redacted)",
"Scope": "email",
"AuthURL": "https://graph.facebook.com/oauth/authorize",
"TokenURL": "https://graph.facebook.com/oauth/access_token",
"RedirectURL": "http://www.example.com/",
}
code := r.FormValue("code")
if code == "" {
// 1. Code request
url := oaConfig["AuthURL"] +
"?client_id=" + oaConfig["ClientID"] +
"&redirect_uri=" + oaConfig["RedirectURL"] +
"&state=SOME_UNIQUE_VALUE"
http.Redirect(w, r, url, http.StatusFound)
}
// 2. Token request
client := urlfetch.Client(c)
tokenResponse, err := client.PostForm(oaConfig["TokenURL"],
url.Values{
"client_id": {oaConfig["ClientID"]},
"redirect_uri": {oaConfig["RedirectURL"]},
"client_secret": {oaConfig["ClientSecret"]},
"code": {code},
})
if err != nil {
// ...
} else {
// 3. Read token from response body
defer tokenResponse.Body.Close()
body, err := ioutil.ReadAll(tokenResponse.Body)
if err != nil {
// ...
} else {
token := string(body)
}
}
// ...
}
When hooked up to a template, this obtains a token response from Facebook and happily displays it. However, it would be nice not to have to redirect the user to example.com/?state=SOME_UNIQUE_VALUE&code=AQB0iYpAf8nMmX5blahblah#= in order to achieve a login.
Is there a way to use client.Get etc to visit the authorise URL, follow the redirect, obtain the code from the resulting query string and stuff it into a string for use by the handler? Without resorting to Ajax, that is.
Is there a way to use client.Get etc to visit the authorise URL, follow the redirect, obtain the code from the resulting query string and stuff it into a string for use by the handler?
No, because the user may have to enter their login credentials to Facebook (and maybe connect to your app too, if they are a first time user) – and that can hardly be done, if you do it all from your server without showing it to the user.
If you want to recognize existing users re-visiting your app when they are already logged in to Facebook – that can only be done client-side. FB.getLoginStatus from the JS SDK is able to do that for you – it will recognize the user, and give you a valid access token for them at the same time.

Resources