Oauth2 autentification library
Works well on the localhost but crashes when is uploaded to the Google App Engine
oauth.go
When it does the line 250 of the above code
r, err := (&http.Client{Transport: t.transport()}).PostForm(t.TokenURL, v)
The error response is "permission denied"
From the api.go documentation :
Since the Google App Engine URL Fetch API requires a per-request
context, you must use the *plus.Service from within an HTTP handler.
This package provides the WithNoAuthPlus and WithOAuthPlus functions
which you can use to wrap your HTTP handlers to provide them with
fully initialized *plus.Services.
Example:
c := appengine.NewContext(r)
trans := &oauth.Transport{
Config: oauthConfig,
Transport: &urlfetch.Transport{Context: c},
}
trans.Exchange(code)
resp, err := trans.Client().Get(profileInfoURL)
Related
I am trying to add a custom domain mapping to my App Engine app using the Google API (not through console). However, I keep getting 403 forbidden error when the http request is made with the Discovery API Client. I have obtained a credentials json file from App Engine with owner permissions and I point to that with the GOOGLE_APPLICATION_CREDENTIALS env variable. Since I have full permissions, I'm guessing the problem is I'm not using the API correctly but haven't been able to see what is missing.
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = os.path.dirname(__file__) + str('/json_cred_file')
apps_client = googleapiclient.discovery.build('appengine', 'v1beta')
response = apps_client.apps().domainMappings().create(
appsId='apps/myappname', body=json.loads(
'{"id": "newsubdomain.mydomain.com","sslSettings": '
'{"sslManagementType": "AUTOMATIC" }}')).execute()
Here is the error:
WARNING 2018-07-06 23:51:09,331 http.py:119] Encountered 403 Forbidden with reason "forbidden"
I contacted Google support and the issue is when using the domain mapping function, the service account needs to be added to the search console as an owner. This is the search console: https://www.google.com/webmasters/tools/home
They have a special page in their docs for using this library on app engine: https://developers.google.com/api-client-library/python/guide/google_app_engine
This is how I use the googleapiclient library. One difference I see is this line:
credentials = GoogleCredentials.get_application_default()
from oauth2client.client import GoogleCredentials
from lib.googleapiclient import discovery
class DataFlowJobsListHandler(AdminResourceHandler):
def get(self, resource_id=None):
"""
Wrapper to this:
https://cloud.google.com/dataflow/docs/reference/rest/v1b3/projects.jobs/list
"""
if resource_id:
self.abort(405)
else:
credentials = GoogleCredentials.get_application_default()
service = discovery.build('dataflow', 'v1b3', credentials=credentials)
project_id = app_identity.get_application_id()
_filter = self.request.GET.pop('filter', 'UNKNOWN').upper()
jobs_list_request = service.projects().jobs().list(
projectId=project_id,
filter=_filter) #'ACTIVE'
jobs_list = jobs_list_request.execute()
return {
'$cursor': None,
'results': jobs_list.get('jobs', []),
}
In GAE I just use a default domain name: https://*.appspot.com, so I don't need to generate self-signed certificates.
Google App Engine docs specify how app.yaml should be configured to serve SSL connections:
https://cloud.google.com/appengine/docs/standard/go/config/appref#handlers_secure
But to serve an HTTPS connection in Go I write the following code example where I need to specify the certificates' filenames:
import (
"net/http"
)
func main() {
go http.ListenAndServeTLS(Address, "cert.pem", "key.pem", nil)
}
I don't understand how in this case to serve SSL requests if I don't generate certificates myself.
You don't need to call http.ListenAndServeTLS on App Engine. If you have your app.yaml set up correctly, traffic will be served over SSL for you. A minimal App Engine app might be something like this:
package main
import (
"fmt"
"net/http"
)
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hi")
}
I have deployed my application without hassle just by running gcloud app deploy command on GCP. Which takes the flexible environment as default. Yesterday I made the necessary customizations to have a custom domain for this app with ssl. Currently it works when I go to any of the following, http://example.com, https://example.com but I also want to force people to use https. Currently the http requests work as they are, I want them to be directed to https. I want to direct any user to https://example.com when they try to go to the website with http or without anything at all like example.com. How can this be achieved?
Here's my app.yaml:
api_version: go1
env: flex
runtime: go
I already tried to use handlers and secure attributes but it seems they are not valid for flexible environment.
Thanks.
Currently, flexible environment does not support HTTPS only directing by using app.yaml. However, this can be achieved in the server code by using a function like this,
func directToHttps(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
if r.URL.Scheme == "https" || strings.HasPrefix(r.Proto, "HTTPS") || r.Header.Get("X-Forwarded-Proto") == "https" {
next(w, r)
} else {
target := "https://" + r.Host + r.URL.Path
http.Redirect(w, r, target,
http.StatusTemporaryRedirect)
}
}
I wrapped this function to my handlers with negroni.
Working example can be found here: https://github.com/malisit/munhasir
I post JSON to an app I registered at Google App Engine but I am baffled by the authentication process in my Go code to get it working in appengine:
func init() {
http.HandleFunc("/post", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
app := appengine.NewContext(r)
client := &http.Client{
Transport: &oauth2.Transport{
Source: google.AppEngineTokenSource(app, "https://www.googleapis.com/auth/bigquery"),
Base: &urlfetch.Transport{
Context: app,
},
},
}
log.Print(client)
}
In following the docs, I have reduced my problem to the code above which consistently gives me the following error:
2015/01/28 09:05:32 appengine: NewContext passed an unknown http.Request
I'd love some pointers as to how I can provide appengine with a "known" http.Request because ultimately I am trying to get to the storage api which also requires a valid context.
Does removing and re go getting google.golang.org/appengine from your GOPATH fixes the issue ?
Edit: Also, a colleague of mine said that after rebooting all went well.
I'm creating a Go Google App Engine application that will be making HTTP JSON RPC calls to a Bitcoin server. I got my code to work properly on the dev_appserver, but when deployed on GAE, the code seems to not work. I'm using a library available on GitHub, and call it like this:
func GetInfo(id interface{})(map[string]interface{}, os.Error){
resp, err:=httpjsonrpc.Call("user:pass#111.1.1.1:18332", "getinfo", id, nil)
if err!=nil{
log.Println(err)
return resp, err
}
return resp, err
}
Which when called should give:
map[proxy: keypoololdest:1.327368259e+09 blocks:45385 keypoolsize:101 connections:11 version:50200 difficulty:8.88353262 generate:false hashespersec:0 paytxfee:0 balance:0 genproclimit:-1 testnet:true errors:]
But on GAE calling the function seems to be causing an error. What part of the code could be working on dev_appserver, but fail on GAE?
You should make you are using urlfetch.Transport to make HTTP calls in production as described in urlfetch documentation.
Instead of doing:
resp, err := http.Post(address,
"application/json", strings.NewReader(string(data)))
You should be doing:
client := urlfetch.Client(context)
resp, error := client.Post(address,
"application/json", strings.NewReader(string(data)))
As you can see in the implementation, urlfetch.Client is just a shortcut to construct an http.Client that uses urlfetch.Transport.