auth.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { HoppRESTAuth } from "@hoppscotch/data"
  2. import parser from "yargs-parser"
  3. import * as O from "fp-ts/Option"
  4. import * as S from "fp-ts/string"
  5. import { pipe } from "fp-ts/function"
  6. import { getDefaultRESTRequest } from "~/newstore/RESTSession"
  7. import { objHasProperty } from "~/helpers/functional/object"
  8. const defaultRESTReq = getDefaultRESTRequest()
  9. const getAuthFromAuthHeader = (headers: Record<string, string>) =>
  10. pipe(
  11. headers.Authorization,
  12. O.fromNullable,
  13. O.map((a) => a.split(" ")),
  14. O.filter((a) => a.length > 1),
  15. O.chain((kv) =>
  16. O.fromNullable(
  17. (() => {
  18. switch (kv[0].toLowerCase()) {
  19. case "bearer":
  20. return <HoppRESTAuth>{
  21. authActive: true,
  22. authType: "bearer",
  23. token: kv[1],
  24. }
  25. case "basic": {
  26. const [username, password] = pipe(
  27. O.tryCatch(() => atob(kv[1])),
  28. O.map(S.split(":")),
  29. // can have a username with no password
  30. O.filter((arr) => arr.length > 0),
  31. O.map(
  32. ([username, password]) =>
  33. <[string, string]>[username, password]
  34. ),
  35. O.getOrElse(() => ["", ""])
  36. )
  37. if (!username) return undefined
  38. return <HoppRESTAuth>{
  39. authActive: true,
  40. authType: "basic",
  41. username,
  42. password: password ?? "",
  43. }
  44. }
  45. default:
  46. return undefined
  47. }
  48. })()
  49. )
  50. )
  51. )
  52. const getAuthFromParsedArgs = (parsedArguments: parser.Arguments) =>
  53. pipe(
  54. parsedArguments,
  55. O.fromPredicate(objHasProperty("u", "string")),
  56. O.chain((args) =>
  57. pipe(
  58. args.u,
  59. S.split(":"),
  60. // can have a username with no password
  61. O.fromPredicate((arr) => arr.length > 0 && arr[0].length > 0),
  62. O.map(
  63. ([username, password]) => <[string, string]>[username, password ?? ""]
  64. )
  65. )
  66. ),
  67. O.map(
  68. ([username, password]) =>
  69. <HoppRESTAuth>{
  70. authActive: true,
  71. authType: "basic",
  72. username,
  73. password,
  74. }
  75. )
  76. )
  77. const getAuthFromURLObject = (urlObject: URL) =>
  78. pipe(
  79. urlObject,
  80. (url) => [url.username, url.password ?? ""],
  81. // can have a username with no password
  82. O.fromPredicate(([username, _]) => !!username && username.length > 0),
  83. O.map(
  84. ([username, password]) =>
  85. <HoppRESTAuth>{
  86. authActive: true,
  87. authType: "basic",
  88. username,
  89. password,
  90. }
  91. )
  92. )
  93. /**
  94. * Preference order:
  95. * - Auth headers
  96. * - --user or -u argument
  97. * - Creds provided along with URL
  98. */
  99. export const getAuthObject = (
  100. parsedArguments: parser.Arguments,
  101. headers: Record<string, string>,
  102. urlObject: URL
  103. ): HoppRESTAuth =>
  104. pipe(
  105. getAuthFromAuthHeader(headers),
  106. O.alt(() => getAuthFromParsedArgs(parsedArguments)),
  107. O.alt(() => getAuthFromURLObject(urlObject)),
  108. O.getOrElse(() => defaultRESTReq.auth)
  109. )