<commit_before>import got from 'got';
import { getUser, setUser } from './user_cache.js';

export async function getToken(request, response) {
  const accessTokenName = 'authorization_code';
  const grantTypes = [accessTokenName, 'refresh_token'];
  if (request.body.client_id !== process.env.CLIENT_ID) {
    return response.status(400).send('invalid client_id');
  } else if (!grantTypes.includes(request.body.grant_type)) {
    return response.status(400).json({
      error_description: `invalid grant_type: ${request.body.grant_type}, must be one of ${grantTypes.join(', ')}`,
      error: 'invalid_request',
    });
  }

  const passed_through_params =
    request.body.grant_type === accessTokenName
      ? ['client_id', 'code_verifier', 'code_challenge', 'redirect_uri', 'code']
      : ['client_id', 'refresh_token'];
  const body = { grant_type: request.body.grant_type };
  try {
    passed_through_params.forEach((name) => {
      const param = request.body[name];
      if (param) {
        body[name] = param;
      } else {
        const error = new Error(`${name} is required`);
        error.status = 400;

        throw error;
      }
    });
  } catch (error) {
    return response.status(400).json({ error_description: error.message, error: 'invalid_request' });
  }

  try {
    const tokenRequest = await got.post('https://login.dts.utah.gov:443/sso/oauth2/access_token', {
      form: body,
      responseType: 'json',
      headers: {
        authorization: request.headers.authorization,
        accept: request.headers.accept,
      },
    });

    return response.send(tokenRequest.body);
  } catch (error) {
    const errorMessage = error.body || error.message || error;

    return response.status(500).json({ error_description: errorMessage, error: 'server_error' });
  }
}

export async function authenticate(request, response, next) {
  if (request.headers.authorization) {
    const token = request.headers.authorization.split(' ').pop();
    const cachedUser = await getUser(token);
    if (cachedUser) {
      response.locals.user = cachedUser;

      return next();
    }

    let userResponse;
    try {
      // TODO: add cache, redis or in_memory
      userResponse = await got('https://login.dts.utah.gov/sso/oauth2/userinfo', {
        responseType: 'json',
        headers: {
          Authorization: request.headers.authorization,
        },
        retry: 5,
        throwHttpErrors: false,
      });
    } catch (error) {
      const errorMessage = error.body || error.message || error;

      return response.status(500).json({ error_description: errorMessage, error: 'server_error' });
    }

    if (userResponse.statusCode === 200 && userResponse.body) {
      response.locals.user = userResponse.body;

      setUser(token, userResponse.body);

      return next();
    }

    response.status(userResponse.statusCode).json(userResponse.body);
  }

  return response.status(401).send('Access denied');
}
<commit_msg>fix(back): use correct status code for bad request<commit_after>import got from 'got';
import { getUser, setUser } from './user_cache.js';

export async function getToken(request, response) {
  const accessTokenName = 'authorization_code';
  const grantTypes = [accessTokenName, 'refresh_token'];
  if (request.body.client_id !== process.env.CLIENT_ID) {
    return response.status(400).send('invalid client_id');
  } else if (!grantTypes.includes(request.body.grant_type)) {
    return response.status(400).json({
      error_description: `invalid grant_type: ${request.body.grant_type}, must be one of ${grantTypes.join(', ')}`,
      error: 'invalid_request',
    });
  }

  const passed_through_params =
    request.body.grant_type === accessTokenName
      ? ['client_id', 'code_verifier', 'code_challenge', 'redirect_uri', 'code']
      : ['client_id', 'refresh_token'];
  const body = { grant_type: request.body.grant_type };
  try {
    passed_through_params.forEach((name) => {
      const param = request.body[name];
      if (param) {
        body[name] = param;
      } else {
        const error = new Error(`${name} is required`);
        error.status = 400;

        throw error;
      }
    });
  } catch (error) {
    return response.status(400).json({ error_description: error.message, error: 'invalid_request' });
  }

  try {
    const tokenRequest = await got.post('https://login.dts.utah.gov:443/sso/oauth2/access_token', {
      form: body,
      responseType: 'json',
      headers: {
        authorization: request.headers.authorization,
        accept: request.headers.accept,
      },
    });

    return response.send(tokenRequest.body);
  } catch (error) {
    const errorMessage = error.body || error.message || error;

    return response.status(500).json({ error_description: errorMessage, error: 'server_error' });
  }
}

export async function authenticate(request, response, next) {
  if (request.headers.authorization) {
    const token = request.headers.authorization.split(' ').pop();
    const cachedUser = await getUser(token);
    if (cachedUser) {
      response.locals.user = cachedUser;

      return next();
    }

    let userResponse;
    try {
      // TODO: add cache, redis or in_memory
      userResponse = await got('https://login.dts.utah.gov/sso/oauth2/userinfo', {
        responseType: 'json',
        headers: {
          Authorization: request.headers.authorization,
        },
        retry: 5,
        throwHttpErrors: false,
      });
    } catch (error) {
      const errorMessage = error.body || error.message || error;

      return response.status(500).json({ error_description: errorMessage, error: 'server_error' });
    }

    if (userResponse.statusCode === 200 && userResponse.body) {
      response.locals.user = userResponse.body;

      setUser(token, userResponse.body);

      return next();
    }

    response.status(userResponse.statusCode).json(userResponse.body);
  }

  return response.status(400).send('authorization header is required');
}

{'fraction_non_alphanumeric': 0.1377755511022044, 'fraction_numerical': 0.01002004008016032, 'mean_word_length': 3.1706128133704734, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6303687', 'n_tokens_mistral': 1852, 'n_tokens_neox': 1771, 'n_words': 379}