func (b *backend) verifyCreds(ctx context.Context, req *logical.Request, token string) (*verifyResp, error) {
	config, err := b.Config(ctx, req.Storage)
	if err != nil {
		return nil, err
	}
	client := slack.New(token, OptionSlackEndpoint(config.Endpoint))
	ctx, cancel := newContext()
	defer cancel()
	resp, err := client.AuthTestContext(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "auth.test")
	}
	team := &slack.Team{
		ID:   resp.TeamID,
		Name: resp.Team,
	}
	found := false
	for _, t := range config.Teams {
		if team.ID == t || team.Name == t {
			found = true
			break
		}
	}
	if !found {
		return nil, logical.CodedError(403, "user is not part of any registered teams")
	}
	client = slack.New(config.AccessToken, OptionSlackEndpoint(config.Endpoint))
	ctx, cancel = newContext()
	defer cancel()
	user, err := client.GetUserInfoContext(ctx, resp.UserID)
	if err != nil {
		return nil, errors.Wrap(err, "users.list")
	}
	switch {
	case user.Deleted:
		return nil, logical.CodedError(403, "user is deleted")
	case user.IsBot && !config.AllowBotUsers:
		return nil, logical.CodedError(403, "user is a bot")
	case !user.Has2FA && !config.AllowNon2FA:
		return nil, logical.CodedError(403, "user does not have 2FA enabled")
	case user.IsRestricted && !config.AllowRestrictedUsers:
		return nil, logical.CodedError(403, "user is a restricted user")
	case user.IsUltraRestricted && !config.AllowUltraRestrictedUsers:
		return nil, logical.CodedError(403, "user is an ultra restricted user")
	}
	ctx, cancel = newContext()
	defer cancel()
	groups, err := client.GetGroupsContext(ctx, true)
	if err != nil {
		return nil, errors.Wrap(err, "groups.list")
	}
	groupIDs := make([]string, 0, len(groups)*2)
	for _, g := range groups {
		if !g.IsArchived {
			groupIDs = append(groupIDs, g.ID)
			groupIDs = append(groupIDs, g.Name)
		}
	}
	ctx, cancel = newContext()
	defer cancel()
	usergroups, err := client.GetUserGroupsContext(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "usergroups.list")
	}
	usergroupIDs := make([]string, 0, len(usergroups)*2)
	for _, u := range usergroups {
		if u.DateDelete == 0 && u.DeletedBy == "" {
			usergroupIDs = append(usergroupIDs, u.ID)
			usergroupIDs = append(usergroupIDs, u.Handle)
		}
	}
	userIDs := []string{user.ID, user.Name}
	groupPolicies, err := b.GroupsMap.Policies(ctx, req.Storage, groupIDs...)
	if err != nil {
		return nil, errors.Wrap(err, "group policies")
	}
	usergroupPolicies, err := b.UsergroupsMap.Policies(ctx, req.Storage, usergroupIDs...)
	if err != nil {
		return nil, errors.Wrap(err, "usergroup policies")
	}
	userPolicies, err := b.UsersMap.Policies(ctx, req.Storage, userIDs...)
	if err != nil {
		return nil, errors.Wrap(err, "user policies")
	}
	policies := make([]string, 0, len(groupPolicies)+len(usergroupPolicies))
	policies = append(policies, groupPolicies...)
	policies = append(policies, usergroupPolicies...)
	policies = append(policies, userPolicies...)
	policies = append(policies, config.AnyonePolicies...)
	uniq := map[string]struct{}{}
	for _, v := range policies {
		if _, ok := uniq[v]; !ok {
			uniq[v] = struct{}{}
		}
	}
	newPolicies := make([]string, 0, len(uniq))
	for k := range uniq {
		newPolicies = append(newPolicies, k)
	}
	policies = newPolicies
	if len(policies) == 0 {
		return nil, logical.CodedError(403, "user has no mapped policies")
	}
	return &verifyResp{
		policies: policies,
		user:     user,
		team:     team,
		ttl:      config.TTL,
		maxTTL:   config.MaxTTL,
	}, nil
}
verifyCreds verifies the given credentials.
package slack
import (
	"context"
	"time"
	"github.com/hashicorp/vault/sdk/framework"
	"github.com/hashicorp/vault/sdk/helper/policyutil"
	"github.com/hashicorp/vault/sdk/logical"
	"github.com/nlopes/slack"
	"github.com/pkg/errors"
)
type verifyResp struct {
	policies []string
	user     *slack.User
	team     *slack.Team
	ttl    time.Duration
	maxTTL time.Duration
}
func (b *backend) pathAuthLogin(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	if err := validateFields(req, d); err != nil {
		return nil, logical.CodedError(422, err.Error())
	}
	token := d.Get("token").(string)
	if token == "" {
		return errMissingField("token"), nil
	}
	creds, err := b.verifyCreds(ctx, req, token)
	if err != nil {
		if err, ok := err.(logical.HTTPCodedError); ok {
			return nil, err
		}
		return nil, logical.ErrPermissionDenied
	}
	return &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"slack_token": token,
			},
			Policies: creds.policies,
			Metadata: map[string]string{
				"slack_team_id":        creds.team.ID,
				"slack_team_name":      creds.team.Name,
				"slack_user_id":        creds.user.ID,
				"slack_user_name":      creds.user.Name,
				"slack_user_real_name": creds.user.RealName,
			},
			DisplayName: creds.user.Name,
			LeaseOptions: logical.LeaseOptions{
				TTL:       creds.ttl,
				Renewable: true,
			},
		},
	}, nil
}
func (b *backend) pathAuthRenew(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	if req.Auth == nil {
		return nil, errors.New("request auth was nil")
	}
	tokenRaw, ok := req.Auth.InternalData["slack_token"]
	if !ok {
		return nil, errors.New("no internal token found in the store")
	}
	token, ok := tokenRaw.(string)
	if !ok {
		return nil, errors.New("stored access token is not a string")
	}
	creds, err := b.verifyCreds(ctx, req, token)
	if err != nil {
		if err, ok := err.(logical.HTTPCodedError); ok {
			return nil, err
		}
		return nil, logical.ErrPermissionDenied
	}
	if !policyutil.EquivalentPolicies(creds.policies, req.Auth.Policies) {
		return nil, errors.New("policies no longer match")
	}
	return framework.LeaseExtend(creds.ttl, creds.maxTTL, b.System())(ctx, req, d)
}