Skip to content

Commit

Permalink
Token parser (#110)
Browse files Browse the repository at this point in the history
* added default keys update interval

* added raw parsers for bearer acquirer

* updated changelog, prep for release
  • Loading branch information
kristinapathak authored Jun 15, 2021
1 parent 72ba2cf commit 19ae566
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 29 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [v0.10.1]
- Added raw parsers for bearer acquirer. [#110](https://github.com/xmidt-org/bascule/pull/110)
- Added default keys update interval value. [#110](https://github.com/xmidt-org/bascule/pull/110)

## [v0.10.0]
- fixed Authorization keys in the constructor to be case sensitive. [#74](https://github.com/xmidt-org/bascule/pull/74)
- Removed unused check. [#79](https://github.com/xmidt-org/bascule/pull/79)
Expand Down Expand Up @@ -99,7 +103,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added constructor, enforcer, and listener alice decorators
- Basic code and structure established

[Unreleased]: https://github.com/xmidt-org/bascule/compare/v0.10.0...HEAD
[Unreleased]: https://github.com/xmidt-org/bascule/compare/v0.10.1...HEAD
[v0.10.1]: https://github.com/xmidt-org/bascule/compare/v0.10.0...v0.10.1
[v0.10.0]: https://github.com/xmidt-org/bascule/compare/v0.9.0...v0.10.0
[v0.9.0]: https://github.com/xmidt-org/bascule/compare/v0.8.1...v0.9.0
[v0.8.1]: https://github.com/xmidt-org/bascule/compare/v0.8.0...v0.8.1
Expand Down
29 changes: 1 addition & 28 deletions acquire/bearer.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2020 Comcast Cable Communications Management, LLC
* Copyright 2021 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,40 +18,13 @@
package acquire

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"sync"
"time"
)

// TokenParser defines the function signature of a bearer token extractor from a payload.
type TokenParser func([]byte) (string, error)

// ParseExpiration defines the function signature of a bearer token expiration date extractor.
type ParseExpiration func([]byte) (time.Time, error)

// DefaultTokenParser extracts a bearer token as defined by a SimpleBearer in a payload.
func DefaultTokenParser(data []byte) (string, error) {
var bearer SimpleBearer

if errUnmarshal := json.Unmarshal(data, &bearer); errUnmarshal != nil {
return "", fmt.Errorf("unable to parse bearer token: %w", errUnmarshal)
}
return bearer.Token, nil
}

// DefaultExpirationParser extracts a bearer token expiration date as defined by a SimpleBearer in a payload.
func DefaultExpirationParser(data []byte) (time.Time, error) {
var bearer SimpleBearer

if errUnmarshal := json.Unmarshal(data, &bearer); errUnmarshal != nil {
return time.Time{}, fmt.Errorf("unable to parse bearer token expiration: %w", errUnmarshal)
}
return time.Now().Add(time.Duration(bearer.ExpiresInSeconds) * time.Second), nil
}

// RemoteBearerTokenAcquirerOptions provides configuration for the RemoteBearerTokenAcquirer.
type RemoteBearerTokenAcquirerOptions struct {
AuthURL string `json:"authURL"`
Expand Down
85 changes: 85 additions & 0 deletions acquire/parsers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Copyright 2021 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package acquire

import (
"encoding/json"
"fmt"
"time"

"github.com/dgrijalva/jwt-go"
"github.com/pkg/errors"
"github.com/spf13/cast"
)

var (
errMissingExpClaim = errors.New("missing exp claim in jwt")
errUnexpectedCasting = errors.New("unexpected casting error")
)

// TokenParser defines the function signature of a bearer token extractor from a payload.
type TokenParser func([]byte) (string, error)

// ParseExpiration defines the function signature of a bearer token expiration date extractor.
type ParseExpiration func([]byte) (time.Time, error)

// DefaultTokenParser extracts a bearer token as defined by a SimpleBearer in a payload.
func DefaultTokenParser(data []byte) (string, error) {
var bearer SimpleBearer

if errUnmarshal := json.Unmarshal(data, &bearer); errUnmarshal != nil {
return "", fmt.Errorf("unable to parse bearer token: %w", errUnmarshal)
}
return bearer.Token, nil
}

// DefaultExpirationParser extracts a bearer token expiration date as defined by a SimpleBearer in a payload.
func DefaultExpirationParser(data []byte) (time.Time, error) {
var bearer SimpleBearer

if errUnmarshal := json.Unmarshal(data, &bearer); errUnmarshal != nil {
return time.Time{}, fmt.Errorf("unable to parse bearer token expiration: %w", errUnmarshal)
}
return time.Now().Add(time.Duration(bearer.ExpiresInSeconds) * time.Second), nil
}

func RawTokenParser(data []byte) (string, error) {
return string(data), nil
}

func RawTokenExpirationParser(data []byte) (time.Time, error) {
p := jwt.Parser{SkipClaimsValidation: true}
token, _, err := p.ParseUnverified(string(data), jwt.MapClaims{})
if err != nil {
return time.Time{}, err
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return time.Time{}, errUnexpectedCasting
}
expVal, ok := claims["exp"]
if !ok {
return time.Time{}, errMissingExpClaim
}

exp, err := cast.ToInt64E(expVal)
if err != nil {
return time.Time{}, err
}
return time.Unix(exp, 0), nil
}
65 changes: 65 additions & 0 deletions acquire/parsers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright 2021 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package acquire

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestRawTokenParser(t *testing.T) {
assert := assert.New(t)
payload := []byte("eyJhbGciOiJSUzI1NiIsImtpZCI6ImRldmVsb3BtZW50IiwidHlwIjoiSldUIn0.eyJhbGxvd2VkUmVzb3VyY2VzIjp7ImFsbG93ZWRQYXJ0bmVycyI6WyJjb21jYXN0Il19LCJhdWQiOiJYTWlEVCIsImNhcGFiaWxpdGllcyI6WyJ4MTppc3N1ZXI6dGVzdDouKjphbGwiLCJ4MTppc3N1ZXI6dWk6YWxsIl0sImV4cCI6MTYyMjE1Nzk4MSwiaWF0IjoxNjIyMDcxNTgxLCJpc3MiOiJkZXZlbG9wbWVudCIsImp0aSI6ImN4ZmkybTZDWnJjaFNoZ1Nzdi1EM3ciLCJuYmYiOjE2MjIwNzE1NjYsInBhcnRuZXItaWQiOiJjb21jYXN0Iiwic3ViIjoiY2xpZW50LXN1cHBsaWVkIiwidHJ1c3QiOjEwMDB9.7QzRWJgxGs1cEZunMOewYCnEDiq2CTDh5R5F47PYhkMVb2KxSf06PRRGN-rQSWPhhBbev1fGgu63mr3yp_VDmdVvHR2oYiKyxP2skJTSzfQmiRyLMYY5LcLn3BObyQxU8EnLhnqGIjpORW0L5Dd4QsaZmXRnkC73yGnJx4XCx0I")
token, err := RawTokenParser(payload)
assert.Equal(string(payload), token)
assert.Nil(err)
}

func TestRawExpirationParser(t *testing.T) {
tcs := []struct {
Description string
Payload []byte
ShouldFail bool
ExpectedTime time.Time
}{
{
Description: "Not a JWT",
Payload: []byte("xyz==abcNotAJWT"),
ShouldFail: true,
},
{
Description: "A jwt",
Payload: []byte("eyJhbGciOiJSUzI1NiIsImtpZCI6ImRldmVsb3BtZW50IiwidHlwIjoiSldUIn0.eyJhbGxvd2VkUmVzb3VyY2VzIjp7ImFsbG93ZWRQYXJ0bmVycyI6WyJjb21jYXN0Il19LCJhdWQiOiJYTWlEVCIsImNhcGFiaWxpdGllcyI6WyJ4MTppc3N1ZXI6dGVzdDouKjphbGwiLCJ4MTppc3N1ZXI6dWk6YWxsIl0sImV4cCI6MTYyMjE1Nzk4MSwiaWF0IjoxNjIyMDcxNTgxLCJpc3MiOiJkZXZlbG9wbWVudCIsImp0aSI6ImN4ZmkybTZDWnJjaFNoZ1Nzdi1EM3ciLCJuYmYiOjE2MjIwNzE1NjYsInBhcnRuZXItaWQiOiJjb21jYXN0Iiwic3ViIjoiY2xpZW50LXN1cHBsaWVkIiwidHJ1c3QiOjEwMDB9.7QzRWJgxGs1cEZunMOewYCnEDiq2CTDh5R5F47PYhkMVb2KxSf06PRRGN-rQSWPhhBbev1fGgu63mr3yp_VDmdVvHR2oYiKyxP2skJTSzfQmiRyLMYY5LcLn3BObyQxU8EnLhnqGIjpORW0L5Dd4QsaZmXRnkC73yGnJx4XCx0I"),
ExpectedTime: time.Unix(1622157981, 0),
},
}

for _, tc := range tcs {
assert := assert.New(t)
exp, err := RawTokenExpirationParser(tc.Payload)
if tc.ShouldFail {
assert.NotNil(err)
assert.Empty(exp)
} else {
assert.Nil(err)
assert.Equal(tc.ExpectedTime, exp)
}
}
}
5 changes: 5 additions & 0 deletions key/resolverFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const (
// if there are any parameters. URI templates accepted by this package have either no parameters
// or exactly one (1) parameter with this name.
KeyIdParameterName = "keyId"

DefaultKeysUpdateInterval = 24 * time.Hour
)

var (
Expand Down Expand Up @@ -139,6 +141,9 @@ func ProvideResolver(key string, optional bool) fx.Option {
}
return nil, fmt.Errorf("%w at key %s", ErrNoResolverFactory, key)
}
if in.R.UpdateInterval < 1 {
in.R.UpdateInterval = DefaultKeysUpdateInterval
}
return in.R.NewResolver()
},
},
Expand Down

0 comments on commit 19ae566

Please sign in to comment.