Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/config/federation.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,25 @@ The `extra_rp_metadata` option is used to add custom key-value pairs to the rely
another_field: another_value
```

## `extra_fe_metadata`
<span class="badge badge-purple" title="Value Type">mapping / object</span>
<span class="badge badge-green" title="If this option is required or optional">optional</span>

The `extra_fe_metadata` option is used to add custom key-value pairs to the `federation_entity` metadata section in the entity configuration.

This option is applied **before** any automatic copying of informational claims (controlled by [`publish_informational_claims_in_federation_entity`](#publish_informational_claims_in_federation_entity)). This means that values specified in `extra_fe_metadata` take precedence over automatically copied claims. If a field is set in `extra_fe_metadata`, it will not be overwritten by the automatic copying mechanism.

When `publish_informational_claims_in_federation_entity` is set to `true` (default), OFFA will still automatically copy consistent informational claims from other metadata sections to the federation entity metadata, but only for fields that are not already defined in `extra_fe_metadata`.

??? file "config.yaml"

```yaml
federation:
extra_fe_metadata:
custom_federation_field: custom_value
another_federation_field: another_value
```

## `extra_entity_configuration_data`
<span class="badge badge-purple" title="Value Type">mapping / object</span>
<span class="badge badge-green" title="If this option is required or optional">optional</span>
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type federationConf struct {
OrganizationName string `yaml:"organization_name"`
OrganizationURI string `yaml:"organization_uri"`
ExtraRPMetadata map[string]any `yaml:"extra_rp_metadata"`
ExtraFEMetadata map[string]any `yaml:"extra_fe_metadata"`
ExtraEntityConfigurationData map[string]any `yaml:"extra_entity_configuration_data"`

ConfigurationLifetime duration.DurationOption `yaml:"configuration_lifetime"`
Expand Down
48 changes: 48 additions & 0 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package server

import (
"fmt"
"reflect"
"strings"
"time"

Expand Down Expand Up @@ -95,6 +96,9 @@ func initFederationEntity() {
OrganizationURI: fedConfig.OrganizationURI,
},
}
if fedConfig.ExtraFEMetadata != nil && len(fedConfig.ExtraFEMetadata) > 0 {
metadata.FederationEntity = applyExtraFEMetadata(fedConfig.ExtraFEMetadata)
}
if metadata.RelyingParty.Extra == nil {
metadata.RelyingParty.Extra = make(map[string]any)
}
Expand Down Expand Up @@ -195,3 +199,47 @@ func getFullPath(path string) string {
}
return config.Get().Server.Basepath + path
}

func applyExtraFEMetadata(extraFE map[string]any) *oidfed.FederationEntityMetadata {
fe := &oidfed.FederationEntityMetadata{}
v := reflect.ValueOf(fe).Elem()
t := v.Type()

jsonTagToField := make(map[string]string)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
jsonTag := field.Tag.Get("json")
if jsonTag != "" && jsonTag != "-" {
if idx := strings.Index(jsonTag, ","); idx != -1 {
jsonTag = jsonTag[:idx]
}
jsonTagToField[jsonTag] = field.Name
}
}

for key, value := range extraFE {
if fieldName, ok := jsonTagToField[key]; ok {
field := v.FieldByName(fieldName)
if field.IsValid() && field.CanSet() {
switch field.Kind() {
case reflect.String:
if strVal, ok := value.(string); ok {
field.SetString(strVal)
}
case reflect.Slice:
if sliceVal, ok := value.([]interface{}); ok {
strSlice := make([]string, len(sliceVal))
for i, v := range sliceVal {
if str, ok := v.(string); ok {
strSlice[i] = str
}
}
field.Set(reflect.ValueOf(strSlice))
}
}
}
}
}

return fe
}
Loading