in lib/dam/token_flow.go [235:367]
func (s *Service) auth(ctx context.Context, in authHandlerIn) (_ *authHandlerOut, ferr error) {
tx, err := s.store.Tx(true)
if err != nil {
return nil, status.Errorf(codes.Unavailable, err.Error())
}
defer func() {
err := tx.Finish()
if ferr == nil && err != nil {
ferr = status.Errorf(codes.Unavailable, err.Error())
}
}()
sec, err := s.loadSecrets(tx)
if err != nil {
return nil, status.Errorf(codes.Unavailable, err.Error())
}
realm := in.realm
if in.tokenType == pb.ResourceTokenRequestState_DATASET {
if len(in.resources) == 0 {
return nil, status.Errorf(codes.FailedPrecondition, "empty resource list")
}
realm = in.resources[0].realm
}
cfg, err := s.loadConfig(tx, realm)
if err != nil {
return nil, status.Errorf(codes.Unavailable, err.Error())
}
broker, ok := cfg.TrustedIssuers[s.defaultBroker]
if !ok {
return nil, status.Errorf(codes.InvalidArgument, "broker %q is not defined", s.defaultBroker)
}
clientSecret, ok := sec.GetBrokerSecrets()[broker.ClientId]
if !ok {
return nil, status.Errorf(codes.FailedPrecondition, "client secret of broker %q is not defined", s.defaultBroker)
}
var list []*pb.ResourceTokenRequestState_Resource
for _, rvr := range in.resources {
if rvr.realm != realm {
return nil, status.Errorf(codes.Aborted, "cannot authorize resources using different realms")
}
resName := rvr.resource
viewName := rvr.view
roleName := rvr.role
interf := rvr.interf
if err := checkName(resName); err != nil {
return nil, status.Errorf(codes.InvalidArgument, err.Error())
}
if err := checkName(viewName); err != nil {
return nil, status.Errorf(codes.InvalidArgument, err.Error())
}
res, ok := cfg.Resources[resName]
if !ok {
return nil, status.Errorf(codes.NotFound, "resource not found: %q", resName)
}
view, ok := res.Views[viewName]
if !ok {
return nil, status.Errorf(codes.NotFound, "view %q not found for resource %q", viewName, resName)
}
grantRole := roleName
if len(grantRole) == 0 {
grantRole = view.DefaultRole
}
if !viewHasRole(view, grantRole) {
return nil, status.Errorf(codes.FailedPrecondition, "role %q is not defined on resource %q view %q", grantRole, resName, viewName)
}
st, ok := cfg.ServiceTemplates[view.ServiceTemplate]
if !ok {
return nil, status.Errorf(codes.Internal, "service template %q is invalid for resource %q view %q", view.ServiceTemplate, resName, viewName)
}
// TODO: remove support for oldResourcePath
if len(interf) == 0 {
for k := range st.Interfaces {
interf = k
break
}
}
if _, ok = st.Interfaces[interf]; !ok {
return nil, status.Errorf(codes.FailedPrecondition, "interface %q is not defined on resource %q view %q service template %q", interf, resName, viewName, view.ServiceTemplate)
}
list = append(list, &pb.ResourceTokenRequestState_Resource{
Realm: rvr.realm,
Resource: resName,
View: viewName,
Role: grantRole,
Interface: interf,
Url: rvr.url,
})
}
// TODO: need support real policy filter
scopes := []string{"openid", "ga4gh_passport_v1", "identities", "account_admin"}
if in.tokenType == pb.ResourceTokenRequestState_ENDPOINT {
scopes = []string{"openid", "identities"}
}
sID := uuid.New()
state := &pb.ResourceTokenRequestState{
Type: in.tokenType,
ClientId: in.clientID,
ClientName: in.clientName,
State: in.stateID,
Broker: s.defaultBroker,
Redirect: in.redirect,
Ttl: int64(in.ttl),
ResponseKeyFile: in.responseKeyFile,
Resources: list,
LoginChallenge: in.challenge,
EpochSeconds: time.Now().Unix(),
Realm: realm,
RequestedAudience: in.requestedAudience,
RequestedScope: in.requestedScope,
}
err = s.store.WriteTx(storage.ResourceTokenRequestStateDataType, storage.DefaultRealm, storage.DefaultUser, sID, storage.LatestRev, state, nil, tx)
if err != nil {
return nil, status.Errorf(codes.Unavailable, err.Error())
}
conf := s.oauthConf(s.defaultBroker, broker, clientSecret, scopes)
return &authHandlerOut{
oauth: conf,
stateID: sID,
}, nil
}