Allow custom JWT service expiry times

This commit is contained in:
Daniel Oaks 2020-04-15 20:09:51 +10:00 committed by Shivaram Lingamneni
parent 0bbb5d121d
commit 9b998a7582
4 changed files with 36 additions and 14 deletions

@ -164,9 +164,13 @@ server:
# these services can integrate with the ircd using JSON Web Tokens (https://jwt.io)
# sometimes referred to with 'EXTJWT'
jwt-services:
# # service name -> secret string the service uses to verify our tokens
# call-host: call-hosting-secret-token
# image-host: image-hosting-secret-token
# # service name
# call-host:
# # custom expiry length, default is 30s
# expiry-in-seconds: 45
# # secret string to verify the generated tokens
# secret: call-hosting-secret-token
# allow use of the RESUME extension over plaintext connections:
# do not enable this unless the ircd is only accessible over internal networks

@ -190,9 +190,13 @@ server:
# these services can integrate with the ircd using JSON Web Tokens (https://jwt.io)
# sometimes referred to with 'EXTJWT'
jwt-services:
# # service name -> secret string the service uses to verify our tokens
# call-host: call-hosting-secret-token
# image-host: image-hosting-secret-token
# # service name
# call-host:
# # custom expiry length, default is 30s
# expiry-in-seconds: 45
# # secret string to verify the generated tokens
# secret: call-hosting-secret-token
# allow use of the RESUME extension over plaintext connections:
# do not enable this unless the ircd is only accessible over internal networks

@ -471,6 +471,11 @@ type TorListenersConfig struct {
MaxConnectionsPerDuration int `yaml:"max-connections-per-duration"`
}
type JwtServiceConfig struct {
ExpiryInSeconds int64 `yaml:"expiry-in-seconds"`
Secret string
}
// Config defines the overall configuration.
type Config struct {
Network struct {
@ -502,9 +507,9 @@ type Config struct {
MOTDFormatting bool `yaml:"motd-formatting"`
ProxyAllowedFrom []string `yaml:"proxy-allowed-from"`
proxyAllowedFromNets []net.IPNet
WebIRC []webircConfig `yaml:"webirc"`
JwtServices map[string]string `yaml:"jwt-services"`
MaxSendQString string `yaml:"max-sendq"`
WebIRC []webircConfig `yaml:"webirc"`
JwtServices map[string]JwtServiceConfig `yaml:"jwt-services"`
MaxSendQString string `yaml:"max-sendq"`
MaxSendQBytes int
AllowPlaintextResume bool `yaml:"allow-plaintext-resume"`
Compatibility struct {
@ -922,6 +927,13 @@ func LoadConfig(filename string) (config *Config, err error) {
config.Server.capValues[caps.Multiline] = multilineCapValue
}
// confirm jwt config
for name, info := range config.Server.JwtServices {
if info.Secret == "" {
return nil, fmt.Errorf("Could not parse jwt-services config, %s service has no secret set", name)
}
}
// handle legacy name 'bouncer' for 'multiclient' section:
if config.Accounts.Bouncer != nil {
config.Accounts.Multiclient = *config.Accounts.Bouncer

@ -922,7 +922,6 @@ func extjwtHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
}
claims := jwt.MapClaims{
"exp": time.Now().Unix() + expireInSeconds,
"iss": server.name,
"sub": client.Nick(),
"account": accountName,
@ -945,8 +944,6 @@ func extjwtHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
}
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// we default to a secret of `*`. if you want a real secret setup a service in the config~
service := "*"
secret := "*"
@ -954,14 +951,19 @@ func extjwtHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
service = strings.ToLower(msg.Params[1])
c := server.Config()
var exists bool
secret, exists = c.Server.JwtServices[service]
info, exists := c.Server.JwtServices[service]
if !exists {
rb.Add(nil, server.name, "FAIL", "EXTJWT", "NO_SUCH_SERVICE", client.t("No such service"))
return false
}
secret = info.Secret
if info.ExpiryInSeconds != 0 {
expireInSeconds = info.ExpiryInSeconds
}
}
claims["exp"] = time.Now().Unix() + expireInSeconds
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(secret))
if err == nil {