-
-
Notifications
You must be signed in to change notification settings - Fork 361
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add bearer_token authenticator (#613)
Adds a new authenticator to work with Kratos' new API token. Works the same as the cookie_session authenticator but checks for a bearer token in the Authorization header (unless overwritten by token_from)
- Loading branch information
Showing
6 changed files
with
554 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"$id": "/.schema/authenticators.bearer_token.schema.json", | ||
"$schema": "http://json-schema.org/draft-07/schema#", | ||
"$ref": "/.schema/config.schema.json#/definitions/configAuthenticatorsBearerToken" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package authn | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/tidwall/gjson" | ||
|
||
"github.com/ory/go-convenience/stringsx" | ||
|
||
"github.com/ory/oathkeeper/driver/configuration" | ||
"github.com/ory/oathkeeper/helper" | ||
"github.com/ory/oathkeeper/pipeline" | ||
) | ||
|
||
func init() { | ||
gjson.AddModifier("this", func(json, arg string) string { | ||
return json | ||
}) | ||
} | ||
|
||
type AuthenticatorBearerTokenFilter struct { | ||
} | ||
|
||
type AuthenticatorBearerTokenConfiguration struct { | ||
CheckSessionURL string `json:"check_session_url"` | ||
BearerTokenLocation *helper.BearerTokenLocation `json:"token_from"` | ||
PreservePath bool `json:"preserve_path"` | ||
ExtraFrom string `json:"extra_from"` | ||
SubjectFrom string `json:"subject_from"` | ||
} | ||
|
||
type AuthenticatorBearerToken struct { | ||
c configuration.Provider | ||
} | ||
|
||
func NewAuthenticatorBearerToken(c configuration.Provider) *AuthenticatorBearerToken { | ||
return &AuthenticatorBearerToken{ | ||
c: c, | ||
} | ||
} | ||
|
||
func (a *AuthenticatorBearerToken) GetID() string { | ||
return "bearer_token" | ||
} | ||
|
||
func (a *AuthenticatorBearerToken) Validate(config json.RawMessage) error { | ||
if !a.c.AuthenticatorIsEnabled(a.GetID()) { | ||
return NewErrAuthenticatorNotEnabled(a) | ||
} | ||
|
||
_, err := a.Config(config) | ||
return err | ||
} | ||
|
||
func (a *AuthenticatorBearerToken) Config(config json.RawMessage) (*AuthenticatorBearerTokenConfiguration, error) { | ||
var c AuthenticatorBearerTokenConfiguration | ||
if err := a.c.AuthenticatorConfig(a.GetID(), config, &c); err != nil { | ||
return nil, NewErrAuthenticatorMisconfigured(a, err) | ||
} | ||
|
||
if len(c.ExtraFrom) == 0 { | ||
c.ExtraFrom = "extra" | ||
} | ||
|
||
if len(c.SubjectFrom) == 0 { | ||
c.SubjectFrom = "sub" | ||
} | ||
|
||
return &c, nil | ||
} | ||
|
||
func (a *AuthenticatorBearerToken) Authenticate(r *http.Request, session *AuthenticationSession, config json.RawMessage, _ pipeline.Rule) error { | ||
cf, err := a.Config(config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
token := helper.BearerTokenFromRequest(r, cf.BearerTokenLocation) | ||
if token == "" { | ||
return errors.WithStack(ErrAuthenticatorNotResponsible) | ||
} | ||
|
||
body, err := forwardRequestToSessionStore(r, cf.CheckSessionURL, cf.PreservePath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var ( | ||
subject string | ||
extra map[string]interface{} | ||
|
||
subjectRaw = []byte(stringsx.Coalesce(gjson.GetBytes(body, cf.SubjectFrom).Raw, "null")) | ||
extraRaw = []byte(stringsx.Coalesce(gjson.GetBytes(body, cf.ExtraFrom).Raw, "null")) | ||
) | ||
|
||
if err = json.Unmarshal(subjectRaw, &subject); err != nil { | ||
return helper.ErrForbidden.WithReasonf("The configured subject_from GJSON path returned an error on JSON output: %s", err.Error()).WithDebugf("GJSON path: %s\nBody: %s\nResult: %s", cf.SubjectFrom, body, subjectRaw).WithTrace(err) | ||
} | ||
|
||
if err = json.Unmarshal(extraRaw, &extra); err != nil { | ||
return helper.ErrForbidden.WithReasonf("The configured extra_from GJSON path returned an error on JSON output: %s", err.Error()).WithDebugf("GJSON path: %s\nBody: %s\nResult: %s", cf.ExtraFrom, body, extraRaw).WithTrace(err) | ||
} | ||
|
||
session.Subject = subject | ||
session.Extra = extra | ||
return nil | ||
} |
Oops, something went wrong.