-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE REQUEST]get username from http basic auth and other types of auth #63
Comments
@tuhao1020 It's difficult to believe that That being said, if you are using Please see: And more specifically: |
@AlbinoGeek Is it possible to provide a callback interface so that users can customize the method to get the user name, role or other informations |
@tuhao1020 you mean in the builtin and iris-contrib middlewares? You can use the I believe this is not necessary as we don't have much of auth middlewares controlled by us. There are hundreds of go packages for that job, I think it's not possible and productive to find all of them and "export" their roles and username, it's like designing a whole new package without any realistic benefits (my opinion). However, if you give me a list of middlewares that you use and need that type of feature, I will see what I can do. |
@kataras considering that I use a simple string token encoded with Base64, and username can be decoded from it. (this is just an example to show you the usage) if I use this middleware, I need to copy all the code and rewrite the builtin function |
OK @tuhao1020,
Further feedback is welcomed! |
@kataras
|
Wait, Anyway, it's fixed now, please try again. |
@kataras OK! it works. |
@tuhao1020 I though of this yesterday and added a I'm also thinking of your proposal, as a more generic view, e.g. to have a Sounds good? |
@kataras Sounds fantastic! 👍 |
Hello @tuhao1020, so far the implementation of that User feature is simple, and the basic auth middleware supports it: // SetUser sets a User for this request.
// It's used by auth middlewares as a common
// method to provide user information to the
// next handlers in the chain.
Context.SetUser(u User)
// User returns the registered User of this request.
// See `SetUser` too.
Context.User() User The package context
import (
"errors"
"time"
)
// ErrNotSupported is fired when a specific method is not implemented
// or not supported entirely.
// Can be used by User implementations when
// an authentication system does not implement a specific, but required,
// method of the User interface.
var ErrNotSupported = errors.New("not supported")
// User is a generic view of an authorized client.
// See `Context.User` and `SetUser` methods for more.
//
// The informational methods starts with a "Get" prefix
// in order to allow the implementation to contain exported
// fields such as `Username` so they can be JSON encoded when necessary.
//
// The caller is free to cast this with the implementation directly
// when special features are offered by the authorization system.
type User interface {
// GetAuthorization should return the authorization method,
// e.g. Basic Authentication.
GetAuthorization() string
// GetAuthorizedAt should return the exact time the
// client has been authorized for the "first" time.
GetAuthorizedAt() time.Time
// GetUsername should return the name of the User.
GetUsername() string
// GetPassword should return the encoded or raw password
// (depends on the implementation) of the User.
GetPassword() string
// GetEmail should return the e-mail of the User.
GetEmail() string
}
// FeaturedUser optional interface that a User can implement.
type FeaturedUser interface {
User
// GetFeatures should optionally return a list of features
// the User implementation offers.
GetFeatures() []UserFeature
}
// UserFeature a type which represents a user's optional feature.
// See `HasUserFeature` function for more.
type UserFeature uint32
// The list of standard UserFeatures.
const (
AuthorizedAtFeature UserFeature = iota
UsernameFeature
PasswordFeature
EmailFeature
)
// HasUserFeature reports whether the "u" User
// implements a specific "feature" User Feature.
//
// It returns ErrNotSupported if a user does not implement
// the FeaturedUser interface.
func HasUserFeature(user User, feature UserFeature) (bool, error) {
if u, ok := user.(FeaturedUser); ok {
for _, f := range u.GetFeatures() {
if f == feature {
return true, nil
}
}
return false, nil
}
return false, ErrNotSupported
}
// SimpleUser is a simple implementation of the User interface.
type SimpleUser struct {
Authorization string `json:"authorization"`
AuthorizedAt time.Time `json:"authorized_at"`
Username string `json:"username"`
Password string `json:"-"`
Email string `json:"email,omitempty"`
Features []UserFeature `json:"-"`
}
var _ User = (*SimpleUser)(nil)
// GetAuthorization returns the authorization method,
// e.g. Basic Authentication.
func (u *SimpleUser) GetAuthorization() string {
return u.Authorization
}
// GetAuthorizedAt returns the exact time the
// client has been authorized for the "first" time.
func (u *SimpleUser) GetAuthorizedAt() time.Time {
return u.AuthorizedAt
}
// GetUsername returns the name of the User.
func (u *SimpleUser) GetUsername() string {
return u.Username
}
// GetPassword returns the raw password of the User.
func (u *SimpleUser) GetPassword() string {
return u.Password
}
// GetEmail returns the e-mail of the User.
func (u *SimpleUser) GetEmail() string {
return u.Email
}
// GetFeatures returns a list of features
// this User implementation offers.
func (u *SimpleUser) GetFeatures() []UserFeature {
if u.Features != nil {
return u.Features
}
var features []UserFeature
if !u.AuthorizedAt.IsZero() {
features = append(features, AuthorizedAtFeature)
}
if u.Username != "" {
features = append(features, UsernameFeature)
}
if u.Password != "" {
features = append(features, PasswordFeature)
}
if u.Email != "" {
features = append(features, EmailFeature)
}
return features
} |
You are well on your way to competing with more robust frameworks by implementing this, very interesting indeed! |
I suggest that the property |
@tuhao1020 Ehh; and here's why "ehh":
|
@AlbinoGeek |
Honestly I would disagree, and that's simply because Golang is a language of interfaces, and he has given a system of I would say it is significantly more common a case that an accounts system is based on email addresses and not usernames in a modern web application. Even more so, those that use OAuth exclusively as the means of providing authentication -- these technically don't user the Examples of services without a concept of a static
I think it's best to err on the side of consistency, with compatibility through overrides as a second runner. It is increasingly common nowadays for a |
Wow I am glad this is going interesting. I am working the last 2 days to provide a jwt user (always based on the context.User interface) implementation too (plus some features). @tuhao1020 I thought about it a lot before Ι came up with that simple User interface solution instead of a map or adding an We must keep the User interface as simple as possible while useful on the majority of the cases and also power developer with the freedom of extending based on the application's requirements. The idea is to have the base As always, it's still under development, except basic authentication the context.User interface is not used anywhere else so far, so we can discuss it further. E.g. change the Username to DisplayName (however that will be confused for basic auth). I am impressed from your comments, exactly the thoughts and the decisions I had while implementing that. Good job guys! |
@tuhao1020, a |
News, so far, except the new
On the Context User feature: @tuhao1020, your feature request is respected with the type MyUser struct {
iris.User
Username string
CustomField string
}
func (u *MyUser) GetUsername() string {
return u.Username
}
// STORE
ctx.SetUser(&MyUser{Username: "myusername", CustomField: "custom field"})
// RETRIEVE
username := ctx.User().GetUsername()
// ...
customField := ctx.User().(*MyUser).CustomField |
@kataras Thanks! I really appreciate your work. Don't worry, I just only have two or three custom fields at most. |
@tuhao1020 I am still working on that all with the JWT, you will be suprised of the new features!! Sleepless for 40 hours |
https://github.com/iris-contrib/middleware/blob/master/casbin/casbin.go#L72
this line of code get
username
only byBasicAuth
In production environment, there will be other types of auth, such as session, token, jwt, OAuth...
The text was updated successfully, but these errors were encountered: