func()

in lib/dam/token_flow.go [384:461]


func (s *Service) loggedIn(ctx context.Context, in loggedInHandlerIn) (_ *loggedInHandlerOut, _ string, 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.Internal, err.Error())
		}
	}()

	state := &pb.ResourceTokenRequestState{}
	err = s.store.ReadTx(storage.ResourceTokenRequestStateDataType, storage.DefaultRealm, storage.DefaultUser, in.stateID, storage.LatestRev, state, tx)
	if err != nil {
		if storage.ErrNotFound(err) {
			return nil, "", status.Errorf(codes.InvalidArgument, err.Error())
		}
		return nil, "", status.Errorf(codes.Unavailable, err.Error())
	}

	if len(in.errStr) > 0 || len(in.errDesc) > 0 {
		return nil, state.LoginChallenge, errutil.WithErrorReason(in.errStr, status.Errorf(codes.Unauthenticated, in.errDesc))
	}

	if len(in.authCode) == 0 {
		return nil, state.LoginChallenge, status.Errorf(codes.InvalidArgument, "no auth code")
	}

	sec, err := s.loadSecrets(tx)
	if err != nil {
		return nil, state.LoginChallenge, status.Errorf(codes.Unavailable, err.Error())
	}

	realm := state.Realm
	cfg, err := s.loadConfig(tx, realm)
	if err != nil {
		return nil, state.LoginChallenge, status.Errorf(codes.Unavailable, err.Error())
	}

	broker, ok := cfg.TrustedIssuers[state.Broker]
	if !ok {
		return nil, state.LoginChallenge, status.Errorf(codes.InvalidArgument, "unknown identity broker %q", state.Broker)
	}

	clientSecret, ok := sec.GetBrokerSecrets()[broker.ClientId]
	if !ok {
		return nil, state.LoginChallenge, status.Errorf(codes.FailedPrecondition, "client secret of broker %q is not defined", s.defaultBroker)
	}

	conf := s.oauthConf(state.Broker, broker, clientSecret, []string{})
	tok, err := conf.Exchange(ctx, in.authCode)
	if err != nil {
		return nil, state.LoginChallenge, status.Errorf(codes.Unauthenticated, "token exchange failed. %s", err)
	}

	id, err := s.upstreamTokenToPassportIdentity(ctx, cfg, tx, tok.AccessToken, broker.ClientId)
	if err != nil {
		return nil, state.LoginChallenge, status.Errorf(codes.Unauthenticated, err.Error())
	}

	var subject string
	if subject, err = s.createOrUpdateAccount(ctx, in.r, id, state.Broker, state.Realm, tx); err != nil {
		return nil, state.LoginChallenge, err
	}

	// Add the upstream id to identities, and change id subject to dam account subject.
	id.Identities[id.Subject] = nil
	id.Subject = subject

	if state.Type == pb.ResourceTokenRequestState_DATASET {
		out, err := s.loggedInForDatasetToken(ctx, id, state, cfg, in.stateID, realm, tx)
		return out, state.LoginChallenge, err
	}

	out, err := s.loggedInForEndpointToken(id, state, in.stateID, tx)
	return out, state.LoginChallenge, err
}