in lib/ic/info_release.go [400:487]
func (s *Service) acceptInformationRelease(r *http.Request) (_, _ string, ferr error) {
stateID := httputils.QueryParam(r, "state")
if len(stateID) == 0 {
return "", "", status.Errorf(codes.InvalidArgument, "missing %q parameter", "state")
}
rcp, err := toRememberedConsentPreference(r)
if err != nil {
return "", "", status.Errorf(codes.InvalidArgument, "accept info release read consent failed: %v", err)
}
tx, err := s.store.Tx(true)
if err != nil {
return "", "", status.Errorf(codes.Unavailable, "accept info release transaction creation failed: %v", err)
}
defer func() {
err := tx.Finish()
if ferr == nil && err != nil {
ferr = status.Errorf(codes.Internal, "accept info release transaction finish failed: %v", err)
}
}()
state := &cpb.LoginState{}
err = s.store.ReadTx(storage.LoginStateDatatype, storage.DefaultRealm, storage.DefaultUser, stateID, storage.LatestRev, state, tx)
if err != nil {
return "", "", status.Errorf(codes.Internal, "accept info release datastore read failed: %v", err)
}
// The temporary state for information releasing process can be only used once.
err = s.store.DeleteTx(storage.LoginStateDatatype, storage.DefaultRealm, storage.DefaultUser, stateID, storage.LatestRev, tx)
if err != nil {
return "", "", status.Errorf(codes.Internal, "accept info release datastore delete failed: %v", err)
}
challenge := state.ConsentChallenge
rcp.ClientName = state.ClientName
// Save RememberedConsent if user select remember it.
if rcp.RequestMatchType != cspb.RememberedConsentPreference_NONE {
if err := s.cleanupRememberedConsent(state.Subject, state.Realm, tx); err != nil {
return challenge, "", err
}
rID := uuid.New()
rcp.RequestedScopes = strings.Split(state.Scope, " ")
err = s.store.WriteTx(storage.RememberedConsentDatatype, state.Realm, state.Subject, rID, storage.LatestRev, rcp, nil, tx)
if err != nil {
return challenge, "", status.Errorf(codes.Internal, "accept info release datastore write remember consent failed: %v", err)
}
}
cfg, err := s.loadConfig(tx, state.Realm)
if err != nil {
return challenge, "", status.Errorf(codes.Internal, "accept info release loadConfig() failed: %v", err)
}
secrets, err := s.loadSecrets(tx)
if err != nil {
return challenge, "", status.Errorf(codes.Internal, "accept info release loadSecrets() failed: %v", err)
}
acct, st, err := s.scim.LoadAccount(state.Subject, state.Realm, false, tx)
if err != nil {
return challenge, "", status.Errorf(httputils.RPCCode(st), "accept info release LoadAccount() failed: %v", err)
}
id, err := s.accountToIdentity(r.Context(), acct, cfg, secrets)
if err != nil {
return challenge, "", status.Errorf(codes.Internal, "accept info release accountToIdentity() failed: %v", err)
}
now := time.Now().Unix()
scoped, err := scopedIdentity(id, rcp, state.Scope, s.getIssuerString(), state.Subject, now, id.NotBefore, id.Expiry)
if err != nil {
return challenge, "", status.Errorf(codes.Internal, "accept info release scopedIdentity() failed: %v", err)
}
if s.useHydra {
addr, err := s.hydraAcceptConsent(scoped, state)
if err != nil {
return challenge, "", status.Errorf(codes.Internal, "accept info release hydraAcceptConsent() failed: %v", err)
}
return challenge, addr, nil
}
return challenge, "", status.Errorf(codes.Unimplemented, "oidc service not supported")
}