This change implements OAuth2 Token Exchange in OP according to RFC 8693 (and client code) Some implementation details: - OP parses and verifies subject/actor tokens natively if they were issued by OP - Third-party tokens verification is also possible by implementing additional storage interface - Token exchange can issue only OP's native tokens (id_token, access_token and refresh_token) with static issuer
88 lines
1.9 KiB
Go
88 lines
1.9 KiB
Go
package storage
|
|
|
|
import (
|
|
"crypto/rsa"
|
|
"strings"
|
|
|
|
"golang.org/x/text/language"
|
|
)
|
|
|
|
type User struct {
|
|
ID string
|
|
Username string
|
|
Password string
|
|
FirstName string
|
|
LastName string
|
|
Email string
|
|
EmailVerified bool
|
|
Phone string
|
|
PhoneVerified bool
|
|
PreferredLanguage language.Tag
|
|
IsAdmin bool
|
|
}
|
|
|
|
type Service struct {
|
|
keys map[string]*rsa.PublicKey
|
|
}
|
|
|
|
type UserStore interface {
|
|
GetUserByID(string) *User
|
|
GetUserByUsername(string) *User
|
|
ExampleClientID() string
|
|
}
|
|
|
|
type userStore struct {
|
|
users map[string]*User
|
|
}
|
|
|
|
func NewUserStore(issuer string) UserStore {
|
|
hostname := strings.Split(strings.Split(issuer, "://")[1], ":")[0]
|
|
return userStore{
|
|
users: map[string]*User{
|
|
"id1": {
|
|
ID: "id1",
|
|
Username: "test-user@" + hostname,
|
|
Password: "verysecure",
|
|
FirstName: "Test",
|
|
LastName: "User",
|
|
Email: "test-user@zitadel.ch",
|
|
EmailVerified: true,
|
|
Phone: "",
|
|
PhoneVerified: false,
|
|
PreferredLanguage: language.German,
|
|
IsAdmin: true,
|
|
},
|
|
"id2": {
|
|
ID: "id2",
|
|
Username: "test-user2",
|
|
Password: "verysecure",
|
|
FirstName: "Test",
|
|
LastName: "User2",
|
|
Email: "test-user2@zitadel.ch",
|
|
EmailVerified: true,
|
|
Phone: "",
|
|
PhoneVerified: false,
|
|
PreferredLanguage: language.German,
|
|
IsAdmin: false,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// ExampleClientID is only used in the example server
|
|
func (u userStore) ExampleClientID() string {
|
|
return "service"
|
|
}
|
|
|
|
func (u userStore) GetUserByID(id string) *User {
|
|
return u.users[id]
|
|
}
|
|
|
|
func (u userStore) GetUserByUsername(username string) *User {
|
|
for _, user := range u.users {
|
|
if user.Username == username {
|
|
return user
|
|
}
|
|
}
|
|
return nil
|
|
}
|