illegal base64 data at input byte 0 in go - go

I am starting with go and jwt.
For testing purpose I have a hardcoded secret.
And a route to get the key
const secretKey = "YOLOSWAG"
var mySigningKey = []byte(secretKey)
var GetTokenHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = jwt.MapClaims{
"admin": true,
"name": "John Doe",
"exp": time.Now().Add(time.Hour * 24).Unix(),
}
tokenString, _ := token.SignedString(mySigningKey)
w.Write([]byte(tokenString))
})
var jwtMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return mySigningKey, nil
},
SigningMethod: jwt.SigningMethodHS256,
})
and later added the jwtMiddleware to my route
r.Handle("/protected", jwtMiddleware.Handler(ProtectedTestHandler)).Methods("GET")
So localhost:3000/protected will output an error Required authorization token not found
this works.
/token will output my token. This works too.
And finally /protected with (in postman) Authorization: Bearer {token}
Will output illegal base64 data at input byte 0
I am really confused why this happens.

Don't use curlies around your token. The documentation in many places is confusing because it wraps your token in curlies. It's meant to represent a placeholder. You're not actually supposed to wrap your token with them. Do NOT do it like this.
Bearer {my-special-token}
It should be done like this
Bearer my-special-token

I'm an absolute newb with GO at the moment as I'm learning this right now but I ran into this same issue and realized that the code I was using to pull the JWT Token out of the Authorization header was leaving a blank space as the first character of the JWT token string. This was presumably causing the string not be base64 decoded.
This was the offending code which was leaving a blank space in front of the. JWT token:
This removed the first 6 chars instead of 5 from the Authorization header to correct the problem.
I ran into this problem when following the tutorial here: https://medium.com/wesionary-team/jwt-authentication-in-golang-with-gin-63dbc0816d55
Repo: https://github.com/Bikash888/jwt-auth

Related

how to pass parameter of the destination to middleware in gin/golang

My problem in short is:
I send my auth token as a parameter to my destination api and it seems like middleware can not access that. How can I access the parameter since the middleware needs that to check the auth conditions?
I am trying to implement a simple authentication/authorization application.
I know that it is common to set auth token in coockies, however, in my use-case, I need it to be implemented differently.
The implementation is: login returns auth token in response body and anytime authentication token is required, it is sent as a parameter "authorization" to the application.
here is the code for my user routers :
func UserRoute(router *gin.Engine) {
user := router.Group("/user")
{
user.POST("/signup", controllers.SignUp)
user.POST("/login", controllers.Login)
user.GET("/validate", middleware.RequireAuth, controllers.Validate)
}
}
validate function in usercontrollers.go:
func Validate(c *gin.Context) {
user, _ := c.Get("user")
c.IndentedJSON(http.StatusOK, gin.H{
"message": user,
})
}
here is the request I send
http://localhost:6000/user/validate?authorization=[My-JWT-Token]
Now when I try to read my auth parameter and use it in my middleware it seems like it does not actually exist:
func RequireAuth(c *gin.Context) {
confs, _ := configs.LoadConfig()
tokenString := c.Param("authorization")
if tokenString == "" {
// this abort case always happens
c.AbortWithStatus(http.StatusUnauthorized)
}
}
1. ctx.Request.URL.Query().Get("authorization")
2. ctx.Query("authorization")

Generate JWT Refresh Token with go-oauth2/oauth2 library

I am generating Oauth2 access tokens with the go library https://github.com/go-oauth2/oauth2 (v3) . I do this with the following go pseudocode:
jwtParams := generates.JWTAccessGenerate{
SignedKey: []byte(secretKey),
SignedMethod: jwt.SigningMethodHS512,
}
manage.Manager.MapAccessGenerate(&jwtParams)
req := oauth2.TokenGenerateRequest{
ClientID: clientId,
UserID: userId,
RedirectURI: redirectUri,
Code: authCode,
}
gt := oauth2.GrantType("authorization_code")
tokenInfo, _ := manage.Manager.GenerateAccessToken(gt, &req)
The result I get is a JWT access token but refresh token is not.
access=XXXX.YYYYY expires=5m0s <== JWT token - OK
refresh=YNFCZUFBWTUEXE5WJMD68W expires=12000h0m0s <== MY ISSUE - Not JWT
How do I get this library to generate a JWT refresh token?
Update 17-Jan-2020: After more research, I noted that many implementations don't bother with JWT representations for refresh tokens, so I may not need to as well. I would still like to know if it's feasible with this library, for future reference.
Store the refresh value, use that refresh to refresh the access token in future:
req := oauth2.TokenGenerateRequest{
ClientID: clientId,
UserID: userId,
RedirectURI: redirectUri,
Code: authCode,
}
req.Refresh = refresh
req.Scope = "owner"
rti, err := manager.RefreshAccessToken(req)
You can also call manager.LoadRefreshToken(accessToken) to load the RefreshToken from accessToken.

Making POST request in Go with formdata and authentication

I'm currently trying to interface with an OAuth api with the example curl command curl -u {client_id}:{client_secret} -d grant_type=client_credentials https://us.battle.net/oauth/token. My current go file is:
package main
import (
"bytes"
"fmt"
"mime/multipart"
"net/http"
)
func checkErr(err error) bool {
if err != nil {
panic(err)
}
return true
}
func authcode(id string, secret string, cli http.Client) string {
//un(trace("authcode"))
var form bytes.Buffer
w := multipart.NewWriter(&form)
_, err := w.CreateFormField("grant_type=client_credentials")
checkErr(err)
req, err := http.NewRequest("POST", "https://us.battle.net/oauth/token", &form)
checkErr(err)
req.SetBasicAuth(id, secret)
resp, err := cli.Do(req)
checkErr(err)
defer resp.Body.Close()
json := make([]byte, 1024)
_, err = resp.Body.Read(json)
checkErr(err)
return string(json)
}
func main() {
//un(trace("main"))
const apiID string = "user"
const apiSecret string = "password"
apiClient := &http.Client{}
auth := authcode(apiID, apiSecret, *apiClient)
fmt.Printf("%s", auth)
}
When I run this I get a response of {"error":"invalid_request","error_description":"Missing grant type"}
For reference, the api flow states:
"To request access tokens, an application must make a POST request with the following multipart form data to the token URI: grant_type=client_credentials
The application must pass basic HTTP auth credentials using the client_id as the user and client_secret as the password."
and the expected response is a json string containing an access token, token type, expiration in seconds, and the scope of functions available with said token
From curl manual we have:
-d, --data <data>
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and
presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to
-F, --form.
Note the content-type application/x-www-form-urlencoded part.
as opposed to:
-F, --form <name=content>
(HTTP SMTP IMAP) For HTTP protocol family, this lets curl emulate a filled-in form in which a user has pressed the submit button. This causes curl to
POST data using the Content-Type multipart/form-data according to RFC 2388.
Therefore based on your curl, mime/multipart is probably not what you're looking for and you should be using Client.PostForm, from the manual of which we have:
The Content-Type header is set to application/x-www-form-urlencoded. To set other headers, use NewRequest and Client.Do.

Google Calendar API invalid_grant getting token (Golang)

I'm trying to retrieve an access token, in order to authenticate users using Oauth2. I'm using mostly code found on google's HOW-TO page for using the Calendar API with golang. The problem is that whenever I try to obtain a token, google sends back this:
Response: {
"error" : "invalid_grant"
}
With the error oauth2: cannot fetch token: 400 Bad Request
As I said, I'm using some code got from google's howto, just slightly modified to fit my needs.
//Somewhere...
authURL = config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
//Somewhere else...
func getClient(ctx context.Context, config *oauth2.Config, code string) *http.Client {
cacheFile := tokenCacheFile()
tok, err := tokenFromFile(cacheFile)
if err != nil {
log.Printf("Google auth code not cached. Obtaining from the web...")
tok, err = getTokenFromWeb(code) //This returns an error
if err == nil {
log.Printf("Got token!")
saveToken("calendar-go-quickstart.json", tok)
} else { //Prevent saving token when error
log.Printf("Couldn't get OAUTH2 token! %s", err)
}
}
return config.Client(ctx, tok)
}
The error occurs at "getTokenFromWeb(code)" (if I understood correctly, code must be some random string, no matter its value, it just needs to be the same during the whole process).
This is the problematic code:
func getTokenFromWeb(code string) (*oauth2.Token, error) {
tok, err := config.Exchange(context.Background(), code)
return tok, err
}
After executing, what I see is that error. I even get the exact same error when trying to copy-paste google's own example code!
Any idea? I really can't find a solution online.
Extra details: using IRIS web framework; using the latest version of google calendar api; using the latest version of Golang; I've created a client ID for OAuth2 on Google Cloud Console; The website has got a trusted SSL cert; it listens on port 80 (HTTP) and 4433 (HTTPS);
Here is Google's example:
// getTokenFromWeb uses Config to request a Token.
// It returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the "+
"authorization code: \n%v\n", authURL)
var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatalf("Unable to read authorization code %v", err)
}
...
}
code is an authorization code given to the user after visiting the displayed link. fmt.Scan() is going to scan the input from the user.
If you're going to be acting on a different user's behalf, you will have to do something similar to this example.
If you're only acting as yourself, you should be able to authenticate as yourself without the code.
Either way, code cannot be a random string.

Not able to pass Bearer token in headers of a GET request in Golang

I am using oauth2 to access a third party API. I can get the access token alright, but when I try to call the API by passing the bearer token in the request headers it gives me 401 (Unauthorized) error. Although it works well when I try to do it via POSTMAN by passing headers as (Authorization: Bearer ). But it does not work using go.
Here is the code sample.
url := "http://api.kounta.com/v1/companies/me.json"
var bearer = "Bearer " + <ACCESS TOKEN HERE>
req, err := http.NewRequest("GET", url, nil)
req.Header.Add("authorization", bearer)
client := urlfetch.Client(context)
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
writer.Write([]byte(body)) // Gives 401 Unauthorized error, though same works using POSTMAN
I was able to solve the problem. Actually the problem was two way.
1) The API end point was doing a redirect (302), which was causing a 302 response and then the other API was being called.
2) GO by default does not forward the headers, thus my bearer token was being lost in the middle.
FIX:
I had to override the client's CheckRedirect function and manually pass the headers to the new request.
client.CheckRedirect = checkRedirectFunc
Here is how I forwarded the headers manually.
func checkRedirectFunc(req *http.Request, via []*http.Request) error {
req.Header.Add("Authorization", via[0].Header.Get("Authorization"))
return nil
}

Resources