Skip to content

Commit 1a0895c

Browse files
authored
Merge pull request #3 from bitinflow/cookie-options
Add cookie options
2 parents ef07ddb + 761960d commit 1a0895c

File tree

9 files changed

+133
-26
lines changed

9 files changed

+133
-26
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
# Changelog
22

3+
## v2.0.4
4+
5+
Add `cookies` option in `ModuleOptions` interface
6+
7+
## v2.0.3
8+
9+
Add ", { external: true }" in navigateTo
310

411
## v2.0.2
512

13+
Fix for `auth` middleware
14+
615
## v2.0.1
716

817
Typo fixes in the GitHub/NPM repo

README.md

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export default defineNuxtConfig({
5454
'/whatever/**': {ssr: false}
5555
},
5656

57-
// using code response type (default)
57+
// example 1: using code response type (default)
5858
oauth: {
5959
endpoints: {
6060
authorization: 'https://example.com/oauth/authorize',
@@ -66,7 +66,7 @@ export default defineNuxtConfig({
6666
scope: ['user:read']
6767
},
6868

69-
// using token response type (not recommended)
69+
// example 2: using token response type (not recommended)
7070
oauth: {
7171
endpoints: {
7272
authorization: 'https://example.com/oauth/authorize',
@@ -86,6 +86,69 @@ This will be your callback url (host is determined by `window.location.origin`):
8686

8787
That's it! You can now use @bitinflow/nuxt-oauth in your Nuxt app ✨
8888

89+
## Module Options
90+
91+
The module provides a set of customizable options to configure OAuth-based authentication for your application. Below is a detailed description of each option and its default values:
92+
93+
### `redirect`
94+
95+
This option defines the URLs for redirection during the authentication process.
96+
97+
- `login` (`string`): The URL to redirect to when a user needs to log in. Default: `/login`.
98+
- `logout` (`string`): The URL to redirect to after logging out. Default: `/`.
99+
- `callback` (`string`): The URL to handle the OAuth callback. Default: `/login`.
100+
- `home` (`string`): The URL to redirect to after successful authentication. Default: `/`.
101+
102+
### `endpoints`
103+
104+
Configures the OAuth server endpoints for authorization, token exchange, and user information retrieval.
105+
106+
- `authorization` (`string`): The OAuth authorization endpoint. Default: `https://example.com/oauth/authorize`.
107+
- `token` (`string`): The OAuth token endpoint. Default: `https://example.com/oauth/token`.
108+
- `userInfo` (`string`): The endpoint to retrieve user information. Default: `https://example.com/api/users/me`.
109+
- `logout` (`string | null`): The endpoint for logging out from the OAuth provider. Default: `null`.
110+
111+
### `refreshToken`
112+
113+
Manages the refresh token settings.
114+
115+
- `maxAge` (`number`): The maximum age (in seconds) for storing the refresh token in cookies. Default: `60 * 60 * 24 * 30` (30 days).
116+
117+
### `cookies`
118+
119+
Configures cookie settings for storing OAuth tokens and related data.
120+
121+
- `prefix` (`string`): A prefix for all cookie names. Default: none.
122+
- `names`: Specific names for different OAuth-related cookies.
123+
- `oauth_user`: The cookie name for storing the OAuth user. Default: `oauth_user`.
124+
- `oauth_state`: The cookie name for storing the OAuth state. Default: `oauth_state`.
125+
- `oauth_code_verifier`: The cookie name for storing the OAuth code verifier. Default: `oauth_code_verifier`.
126+
- `oauth_access_token`: The cookie name for storing the access token. Default: `oauth_access_token`.
127+
- `oauth_refresh_token`: The cookie name for storing the refresh token. Default: `oauth_refresh_token`.
128+
- `options`: Additional settings for cookie behavior.
129+
- `path` (`string`): The cookie path. Default: none.
130+
- `maxAge` (`number`): The cookie's maximum age (in seconds). Default: none.
131+
- `secure` (`boolean`): Whether the cookie should only be sent over HTTPS. Default: none.
132+
- `sameSite` (`string`): Sets the `SameSite` cookie attribute (`lax`, `strict`, or `none`). Default: none.
133+
- `domain` (`string`): Specifies the cookie's domain. Default: none.
134+
- `httpOnly` (`boolean`): Indicates if the cookie is inaccessible to JavaScript. Default: none.
135+
136+
### `clientId`
137+
138+
- (`string`): The client ID used for OAuth authentication. Default: `please-set-client-id`.
139+
140+
### `responseType`
141+
142+
- (`'token' | 'code'`): The type of OAuth response, either token-based or code-based flow. Default: `code`.
143+
144+
### `prompt`
145+
146+
- (`'' | 'none' | 'login' | 'consent'`): The prompt parameter to control the OAuth flow. Default: `''`.
147+
148+
### `scope`
149+
150+
- (`string[]`): The OAuth scopes requested during authentication. Default: `[]` (empty array).
151+
89152
## Development
90153

91154
```bash

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bitinflow/nuxt-oauth",
3-
"version": "2.0.3",
3+
"version": "2.0.4",
44
"description": "Nuxt 3 OAuth Module",
55
"license": "MIT",
66
"type": "module",
@@ -37,7 +37,7 @@
3737
"@nuxt/module-builder": "^0.2.1",
3838
"@nuxt/schema": "^3.2.2",
3939
"@nuxt/test-utils": "^3.2.2",
40-
"axios": "^1.3.5",
40+
"axios": "^1.6.0",
4141
"changelogen": "^0.4.1",
4242
"eslint": "^8.34.0",
4343
"nuxt": "^3.2.2",

playground/nuxt.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ export default defineNuxtConfig({
77
redirect: {
88
home: '/home'
99
},
10+
cookies: {
11+
options: {
12+
domain: '*.own3d.pro'
13+
}
14+
},
1015
clientId: '98e1cb74-125a-4d60-b686-02c2f0c87521',
1116
scope: ['user:read']
1217
},

src/module.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ export interface ModuleOptions {
1818
refreshToken?: {
1919
maxAge: number,
2020
}
21+
cookies?: {
22+
prefix?: string,
23+
names?: {
24+
oauth_user?: 'oauth_user'
25+
oauth_state?: 'oauth_state'
26+
oauth_code_verifier?: 'oauth_code_verifier'
27+
oauth_access_token?: 'oauth_access_token'
28+
oauth_refresh_token?: 'oauth_refresh_token'
29+
}
30+
options?: {
31+
path?: string,
32+
maxAge?: number,
33+
secure?: boolean,
34+
sameSite?: string,
35+
domain?: string,
36+
httpOnly?: boolean
37+
}
38+
}
2139
clientId?: string,
2240
responseType?: 'token' | 'code',
2341
prompt?: '' | 'none' | 'login' | 'consent',
@@ -32,9 +50,9 @@ const defaults: ModuleOptions = {
3250
home: '/'
3351
},
3452
endpoints: {
35-
authorization: 'https://accounts.bitinflow.com/oauth/authorize',
36-
token: 'https://accounts.bitinflow.com/oauth/token',
37-
userInfo: 'https://accounts.bitinflow.com/api/v3/user',
53+
authorization: 'https://example.com/oauth/authorize',
54+
token: 'https://example.com/oauth/token',
55+
userInfo: 'https://example.com/api/users/me',
3856
logout: null,
3957
},
4058
refreshToken: {

src/runtime/composables/useAuth.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import {CookieRef, navigateTo, useCookie, useRuntimeConfig} from "#app";
1+
import {CookieRef, navigateTo, useRuntimeConfig} from "#app";
22
import {ModuleOptions} from "../../module";
3-
import {generateRandomString, getChallengeFromVerifier} from "../support";
3+
import { generateRandomString, getChallengeFromVerifier, useCookie } from '../support'
44

55
declare interface ComposableOptions {
66
fetchUserOnInitialization: boolean
@@ -14,9 +14,9 @@ export default async (options: ComposableOptions = {
1414
fetchUserOnInitialization: false
1515
}) => {
1616
const authConfig = useRuntimeConfig().public.oauth as ModuleOptions;
17-
if (user == null) user = useCookie('oauth_user');
18-
if (accessToken == null) accessToken = useCookie('oauth_access_token');
19-
if (refreshToken == null) refreshToken = useCookie('oauth_refresh_token');
17+
if (user == null) user = useCookie('oauth_user', authConfig);
18+
if (accessToken == null) accessToken = useCookie('oauth_access_token', authConfig);
19+
if (refreshToken == null) refreshToken = useCookie('oauth_refresh_token', authConfig);
2020

2121
const fetchUser = async (): Promise<void> => {
2222
try {
@@ -36,7 +36,7 @@ export default async (options: ComposableOptions = {
3636
}
3737

3838
const signIn = async (): Promise<void> => {
39-
const state = useCookie<string>('oauth_state');
39+
const state = useCookie<string>('oauth_state', authConfig);
4040
state.value = generateRandomString();
4141

4242
// create oauth authorization url
@@ -50,7 +50,7 @@ export default async (options: ComposableOptions = {
5050
})
5151

5252
if (authConfig.responseType === 'code') {
53-
const codeVerifier = useCookie<string>('oauth_code_verifier');
53+
const codeVerifier = useCookie<string>('oauth_code_verifier', authConfig);
5454
codeVerifier.value = generateRandomString();
5555

5656
params.set('code_challenge', await getChallengeFromVerifier(codeVerifier.value))

src/runtime/plugin.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import {addRouteMiddleware, defineNuxtPlugin, navigateTo, useCookie} from '#app'
1+
import {addRouteMiddleware, defineNuxtPlugin, navigateTo} from '#app'
22
import useAuth from "./composables/useAuth"
33
import {RouteLocationNormalized} from "vue-router";
44
import {ModuleOptions} from "../module";
5+
import {useCookie} from "./support";
56

67
interface AccessToken {
78
access_token: string,
@@ -39,8 +40,9 @@ export default defineNuxtPlugin(() => {
3940
if (to.query['code']) {
4041
const code = to.query['code'] as string;
4142
const stateFromRequest = to.query['state'] as string;
42-
const stateFromCookie = useCookie<string>('oauth_state');
43-
const codeVerifier = useCookie<string>('oauth_code_verifier');
43+
console.log('options', authConfig.cookies?.options)
44+
const stateFromCookie = useCookie<string>('oauth_state', authConfig);
45+
const codeVerifier = useCookie<string>('oauth_code_verifier', authConfig);
4446

4547
if (stateFromRequest !== stateFromCookie.value) {
4648
console.warn('State mismatch', stateFromRequest, stateFromCookie.value)

src/runtime/support.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
* Source: https://docs.cotter.app/sdk-reference/api-for-other-mobile-apps/api-for-mobile-apps
33
*/
44

5+
import { ModuleOptions } from '../module'
6+
import {useCookie as _useCookie, CookieRef} from "#app";
7+
58
function dec2hex(dec: any) {
69
return ('0' + dec.toString(16)).substr(-2)
710
}
@@ -34,3 +37,10 @@ function base64urlencode(a: any) {
3437
export async function getChallengeFromVerifier(v: any) {
3538
return base64urlencode(await sha256(v));
3639
}
40+
41+
export function useCookie<T = string | null | undefined>(name: string, options: ModuleOptions): CookieRef<T> {
42+
const cookieName = options.cookies?.names?.[name] || name;
43+
const cookiePrefix = options.cookies?.prefix || '';
44+
const cookieOptions = options.cookies?.options || {};
45+
return _useCookie(cookiePrefix + cookieName, cookieOptions)
46+
}

yarn.lock

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,12 +1680,12 @@ autoprefixer@^10.4.15:
16801680
picocolors "^1.0.0"
16811681
postcss-value-parser "^4.2.0"
16821682

1683-
axios@^1.3.5:
1684-
version "1.5.0"
1685-
resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267"
1686-
integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==
1683+
axios@^1.6.0:
1684+
version "1.7.7"
1685+
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
1686+
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
16871687
dependencies:
1688-
follow-redirects "^1.15.0"
1688+
follow-redirects "^1.15.6"
16891689
form-data "^4.0.0"
16901690
proxy-from-env "^1.1.0"
16911691

@@ -2809,10 +2809,10 @@ flatted@^3.2.7:
28092809
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
28102810
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
28112811

2812-
follow-redirects@^1.15.0:
2813-
version "1.15.2"
2814-
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
2815-
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
2812+
follow-redirects@^1.15.6:
2813+
version "1.15.9"
2814+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
2815+
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
28162816

28172817
form-data@^4.0.0:
28182818
version "4.0.0"

0 commit comments

Comments
 (0)