Introducing OAuth 2.0 and OpenID Connect
OAuth 2.0 is an authorization framework that allows third-party applications to access limited resources on behalf of a user without exposing the user’s credentials. OpenID Connect is an identity layer built on top of OAuth 2.0 to provide authentication capabilities. Together, they can securely authenticate users and authorize access to protected resources.
This article will show you how to implement OAuth 2.0 and OpenID Connect in your Node.js Express application. Simplify the process with Passport.js, a popular middleware for authentication.
prerequisite
Before you start, make sure you have the following installed on your machine:
- Node.js (v14 and above)
- npm (v6 and above)
- A code editor (such as Visual Studio Code)
Setting up a Node.js Express application
First, create a new directory for your project and navigate to it in your terminal. Then use npm to initialize your project.
1 2 3 4 | <span class="token function">mkdir</span> oauth-openid-nodejs <span class="token builtin class-name">cd</span> oauth-openid-nodejs <span class="token function">npm</span> init -y |
Install dependencies
Then install the required packages.
1 2 | <span class="token function">npm</span> <span class="token function">install</span> express passport passport-openidconnect dotenv |
Create an Express server
Create an index.js
file in the root of your project and add code to configure a basic Express server.
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'express'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">send</span> <span class="token punctuation">(</span> <span class="token string">'OAuth 2.0とOpenID Connectデモへようこそ!'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">PORT</span> <span class="token operator">=</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">3000</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">listen</span> <span class="token punctuation">(</span> <span class="token constant">PORT</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">Server running on http://localhost:</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token constant">PORT</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
How to use OpenID Connect with Passport.js
Passport.js settings
First, create .env
file in the root of your project to store your client id, client secret and callback url. These are provided by your chosen authentication provider (Google, Facebook, etc.).
1 2 3 4 | CLIENT_ID=your_client_id CLIENT_SECRET=your_client_secret CALLBACK_URL=http://localhost:3000/auth/callback |
Next, create a passport-setup.js
file in the root of your project and add code to configure Passport.js with the OpenID Connect strategy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span class="token keyword">const</span> passport <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'passport'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> OidcStrategy <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'passport-openidconnect'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> Strategy <span class="token punctuation">;</span> <span class="token keyword">const</span> dotenv <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'dotenv'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> dotenv <span class="token punctuation">.</span> <span class="token function">config</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> passport <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token keyword">new</span> <span class="token class-name">OidcStrategy</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> issuer <span class="token operator">:</span> <span class="token string">'https://your-auth-provider.com'</span> <span class="token punctuation">,</span> clientID <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">CLIENT_ID</span> <span class="token punctuation">,</span> clientSecret <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">CLIENT_SECRET</span> <span class="token punctuation">,</span> callbackURL <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">CALLBACK_URL</span> <span class="token punctuation">,</span> scope <span class="token operator">:</span> <span class="token string">'openid profile email'</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">accessToken <span class="token punctuation">,</span> refreshToken <span class="token punctuation">,</span> profile <span class="token punctuation">,</span> done</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">done</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> profile <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> passport <span class="token punctuation">.</span> <span class="token function">serializeUser</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">user <span class="token punctuation">,</span> done</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">done</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> user <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> passport <span class="token punctuation">.</span> <span class="token function">deserializeUser</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">user <span class="token punctuation">,</span> done</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">done</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> user <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> module <span class="token punctuation">.</span> exports <span class="token operator">=</span> passport <span class="token punctuation">;</span> |
Replace https://your-auth-provider.com
with the appropriate issuer URL for your chosen authentication provider.
Update Express Server
Next, update the index.js
file to include Passport.js and OpenID Connect settings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'express'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> passport <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'./passport-setup'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">'express-session'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Expressでセッションミドルウェアを使用するように設定</span> app <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token function">session</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> secret <span class="token operator">:</span> <span class="token string">'your-session-secret'</span> <span class="token punctuation">,</span> resave <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> saveUninitialized <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Passport.jsとセッションサポートを初期化</span> app <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> passport <span class="token punctuation">.</span> <span class="token function">initialize</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> passport <span class="token punctuation">.</span> <span class="token function">session</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">send</span> <span class="token punctuation">(</span> <span class="token string">'OAuth 2.0とOpenID Connectデモへようこそ!'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// OAuth 2.0認証のためのルートを追加</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/auth'</span> <span class="token punctuation">,</span> passport <span class="token punctuation">.</span> <span class="token function">authenticate</span> <span class="token punctuation">(</span> <span class="token string">'openidconnect'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// OAuth 2.0コールバックのためのルートを追加</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/auth/callback'</span> <span class="token punctuation">,</span> passport <span class="token punctuation">.</span> <span class="token function">authenticate</span> <span class="token punctuation">(</span> <span class="token string">'openidconnect'</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> failureRedirect <span class="token operator">:</span> <span class="token string">'/login'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">redirect</span> <span class="token punctuation">(</span> <span class="token string">'/profile'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// ユーザープロファイルのためのルートを追加</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/profile'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> req <span class="token punctuation">.</span> user <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> res <span class="token punctuation">.</span> <span class="token function">redirect</span> <span class="token punctuation">(</span> <span class="token string">'/login'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> res <span class="token punctuation">.</span> <span class="token function">send</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">こんにちは、</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> req <span class="token punctuation">.</span> user <span class="token punctuation">.</span> displayName <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">さん!</span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// ログインページのためのルートを追加</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/login'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">send</span> <span class="token punctuation">(</span> <span class="token string">'<a href="/auth">アイデンティティプロバイダーでログイン</a>'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">PORT</span> <span class="token operator">=</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">3000</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">listen</span> <span class="token punctuation">(</span> <span class="token constant">PORT</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">Server running on http://localhost:</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token constant">PORT</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Application testing
You are now ready to test your Node.js Express application using OAuth 2.0 and OpenID Connect. To start the server, run the following command:
1 2 | node index.js |
Point your browser to http://localhost:3000/login
and click the “Login with Identity Provider” link. You will be redirected to your authentication provider’s login page. After logging in, you will be redirected to the /profile
route and see a personal greeting with your display name.
summary
In this article, we’ve shown how to implement OAuth 2.0 and OpenID Connect in a Node.js Express application using Passport.js. This secure authentication method allows users to authenticate without exposing their credentials to applications, resulting in a more secure and reliable authentication process.
When deploying your application to production, remember to replace the sample configuration information (Issuer URL, Client ID, Client Secret, etc.) with your actual authentication provider information.
last
I am always indebted. I hope you enjoyed this article and learned something new.
See you in the next article! If you like this article, please hit “LIKE” and subscribe to support me. thank you very much.