Skip to content

Commit 01e86a7

Browse files
committed
feat: add util to obtain b64 header from user/pass
1 parent 13275b0 commit 01e86a7

3 files changed

Lines changed: 84 additions & 44 deletions

File tree

README.md

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,29 @@
1616

1717
## The problem
1818

19-
I'm usually repeating a section of code for extract credentials (username and password) given an authorization header.
20-
This utility wants to extract this logic to reuse it across my different projects.
19+
I'm usually repeating code when I was working with Basic Authentication. This
20+
type of authentication uses Base64 encoding so it's very usual to extract
21+
credentials (username and password) given an authorization header or, given the
22+
credentials, build the header. This utility wants to extract this logic to reuse
23+
it across my different projects.
2124

2225
## This solution
2326

24-
It's a simple utility function which, process your request headers and return an object with the username and the password or an Error if:
27+
It's a simple set of utility functions that:
2528

26-
- The authorization (or Authorization) header is not given.
27-
- Its format is not correct.
29+
- process your request headers and return an object with the username and the
30+
password or an Error if:
2831

32+
- The authorization (or Authorization) header is not given.
33+
- Its format is not correct.
34+
35+
- given a username and password, returns a Basic header.
2936

3037
## Table of Contents
3138

3239
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
3340
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3441

35-
- [The problem](#the-problem)
36-
- [This solution](#this-solution)
37-
- [Table of Contents](#table-of-contents)
3842
- [Installation](#installation)
3943
- [Usage](#usage)
4044
- [Other Solutions](#other-solutions)
@@ -57,12 +61,22 @@ npm install --save @ricveal/basic-auth-utils
5761

5862
## Usage
5963

60-
Once it's installed as dependency, you only have to import it and use it with a `headers` object:
64+
Once it's installed as dependency, you only have to import it and use the util
65+
you prefer:
66+
67+
```ts
68+
import {
69+
getUsernameAndPasswordFromAuthBasic,
70+
getAuthBasicFromUsernameAndPassword,
71+
} from '@ricveal/basic-auth-utils'
72+
73+
const headers = {
74+
authorization: 'Basic dXNlcjp0ZXN0',
75+
}
76+
const {username, password} = getUsernameAndPasswordFromAuthBasic(headers)
77+
console.log(username, password) // 'user', 'test'
6178

62-
```js
63-
const headers = { authorization: 'Basic dXNlcjp0ZXN0' }
64-
const credentials = getUsernameAndPasswordFromAuthBasic(headers)
65-
// credentials = { username: "user", password: "test" }
79+
console.log(getAuthBasicFromUsernameAndPassword('user', 'test')) // 'Basic dXNlcjp0ZXN0'
6680
```
6781

6882
## Other Solutions

src/__tests__/index.ts

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,65 @@
1-
import { getUsernameAndPasswordFromAuthBasic } from "../index";
1+
import {
2+
getAuthBasicFromUsernameAndPassword,
3+
getUsernameAndPasswordFromAuthBasic,
4+
} from '../index'
25

36
describe('Get Username and Password From Headers', () => {
47
it('should throw an error when headers input objet is empty', () => {
58
const headers = {}
69
const t = () => {
710
getUsernameAndPasswordFromAuthBasic(headers)
8-
};
9-
expect(t).toThrowError('Invalid or Missing Authorization header');
10-
});
11+
}
12+
expect(t).toThrowError('Invalid or Missing Authorization header')
13+
})
1114
it('should throw an error when headers input objet has not "authorization" or "Authorization" entries', () => {
12-
const headers = { "test": "value" }
15+
const headers = {test: 'value'}
1316
const t = () => {
1417
getUsernameAndPasswordFromAuthBasic(headers)
15-
};
16-
expect(t).toThrowError();
17-
});
18+
}
19+
expect(t).toThrowError()
20+
})
1821
it('should throw an error when authorization header has not start with "Basic "', () => {
19-
const headers = { authorization: 'test value' }
22+
const headers = {authorization: 'test value'}
2023
const t = () => {
2124
getUsernameAndPasswordFromAuthBasic(headers)
22-
};
23-
expect(t).toThrowError();
24-
});
25+
}
26+
expect(t).toThrowError()
27+
})
2528
it('should throw an error when Authorization header has not start with "Basic "', () => {
26-
const headers = { Authorization: 'test value' }
29+
const headers = {Authorization: 'test value'}
2730
const t = () => {
2831
getUsernameAndPasswordFromAuthBasic(headers)
29-
};
30-
expect(t).toThrowError();
31-
});
32+
}
33+
expect(t).toThrowError()
34+
})
3235
it('should return username and password when authorization header is properly set', () => {
33-
const headers = { authorization: 'Basic dXNlcjp0ZXN0' }
34-
expect(getUsernameAndPasswordFromAuthBasic(headers)).toEqual({username: "user", password: "test"})
35-
});
36+
const headers = {authorization: 'Basic dXNlcjp0ZXN0'}
37+
expect(getUsernameAndPasswordFromAuthBasic(headers)).toEqual({
38+
username: 'user',
39+
password: 'test',
40+
})
41+
})
3642
it('should return username and password when Authorization header is properly set', () => {
37-
const headers = { Authorization: 'Basic dXNlcjp0ZXN0' }
38-
expect(getUsernameAndPasswordFromAuthBasic(headers)).toEqual({username: "user", password: "test"})
39-
});
43+
const headers = {Authorization: 'Basic dXNlcjp0ZXN0'}
44+
expect(getUsernameAndPasswordFromAuthBasic(headers)).toEqual({
45+
username: 'user',
46+
password: 'test',
47+
})
48+
})
4049
it('should return username and password when both authorization Authorization header is properly set', () => {
41-
const headers = { authorization: 'Basic dXNlcjp0ZXN0', Authorization: 'Basic dXNlcjp0ZXN0' }
42-
expect(getUsernameAndPasswordFromAuthBasic(headers)).toEqual({username: "user", password: "test"})
43-
});
44-
});
50+
const headers = {
51+
authorization: 'Basic dXNlcjp0ZXN0',
52+
Authorization: 'Basic dXNlcjp0ZXN0',
53+
}
54+
expect(getUsernameAndPasswordFromAuthBasic(headers)).toEqual({
55+
username: 'user',
56+
password: 'test',
57+
})
58+
})
59+
})
60+
61+
describe('should return b64 string from username and password', () => {
62+
expect(getAuthBasicFromUsernameAndPassword('user', 'test')).toEqual(
63+
'Basic dXNlcjp0ZXN0',
64+
)
65+
})

src/index.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ interface Headers {
55
}
66

77
export const getUsernameAndPasswordFromAuthBasic = (headers: Headers) => {
8-
const authHeader = headers.authorization ?? headers.Authorization;
9-
if (
10-
!authHeader ||
11-
!authHeader.includes('Basic ')
12-
) {
8+
const authHeader = headers.authorization ?? headers.Authorization
9+
if (!authHeader || !authHeader.includes('Basic ')) {
1310
throw new Error('Invalid or Missing Authorization header')
1411
}
1512

@@ -19,3 +16,11 @@ export const getUsernameAndPasswordFromAuthBasic = (headers: Headers) => {
1916
const [username, password] = credentials.split(':')
2017
return {username, password}
2118
}
19+
20+
export const getAuthBasicFromUsernameAndPassword = (
21+
username: string,
22+
password: string,
23+
) => {
24+
const encode = Buffer.from(`${username}:${password}`).toString('base64')
25+
return `Basic ${encode}`
26+
}

0 commit comments

Comments
 (0)