Skip to content

Ch 2 node api deps #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 116 additions & 116 deletions 2-Authorization/0-call-api-vanillajs/SPA/public/fetch.js
Original file line number Diff line number Diff line change
@@ -1,116 +1,116 @@
/**
* Execute a fetch request with the given options
* @param {string} method: GET, POST, PUT, DELETE
* @param {String} endpoint: The endpoint to call
* @param {Object} data: The data to send to the endpoint, if any
* @returns response
*/
function callApi(method, endpoint, token, data = null) {
const headers = new Headers();
const bearer = `Bearer ${token}`;

headers.append('Authorization', bearer);

if (data) {
headers.append('Content-Type', 'application/json');
}

const options = {
method: method,
headers: headers,
body: data ? JSON.stringify(data) : null,
};

return fetch(endpoint, options)
.then((response) => {
const contentType = response.headers.get("content-type");

if (contentType && contentType.indexOf("application/json") !== -1) {
return response.json();
} else {
return response;
}
});
}


/**
* Handles todolist actions
* @param {Object} task
* @param {string} method
* @param {string} endpoint
*/
async function handleToDoListActions(task, method, endpoint) {
let listData;

try {
const accessToken = await getToken();
const data = await callApi(method, endpoint, accessToken, task);

switch (method) {
case 'POST':
listData = JSON.parse(localStorage.getItem('todolist'));
listData = [data, ...listData];
localStorage.setItem('todolist', JSON.stringify(listData));
AddTaskToToDoList(data);
break;
case 'DELETE':
listData = JSON.parse(localStorage.getItem('todolist'));
const index = listData.findIndex((todoItem) => todoItem.id === task.id);
localStorage.setItem('todolist', JSON.stringify([...listData.splice(index, 1)]));
showToDoListItems(listData);
break;
default:
console.log('Unrecognized method.')
break;
}
} catch (error) {
console.error(error);
}
}

/**
* Handles todolist action GET action.
*/
async function getToDos() {
try {
const accessToken = await getToken();

const data = await callApi(
'GET',
protectedResources.toDoListAPI.endpoint,
accessToken
);

if (data) {
localStorage.setItem('todolist', JSON.stringify(data));
showToDoListItems(data);
}
} catch (error) {
console.error(error);
}
}

/**
* Retrieves an access token.
*/
async function getToken() {
let tokenResponse;

if (typeof getTokenPopup === 'function') {
tokenResponse = await getTokenPopup({
scopes: [...protectedResources.toDoListAPI.scopes.read],
redirectUri: '/redirect'
});
} else {
tokenResponse = await getTokenRedirect({
scopes: [...protectedResources.toDoListAPI.scopes.read],
});
}

if (!tokenResponse) {
return null;
}

return tokenResponse.accessToken;
}
/**
* Execute a fetch request with the given options
* @param {string} method: GET, POST, PUT, DELETE
* @param {String} endpoint: The endpoint to call
* @param {Object} data: The data to send to the endpoint, if any
* @returns response
*/
function callApi(method, endpoint, token, data = null) {
const headers = new Headers();
const bearer = `Bearer ${token}`;
headers.append('Authorization', bearer);
if (data) {
headers.append('Content-Type', 'application/json');
}
const options = {
method: method,
headers: headers,
body: data ? JSON.stringify(data) : null,
};
return fetch(endpoint, options)
.then((response) => {
const contentType = response.headers.get("content-type");
if (contentType && contentType.indexOf("application/json") !== -1) {
return response.json();
} else {
return response;
}
});
}
/**
* Handles todolist actions
* @param {Object} task
* @param {string} method
* @param {string} endpoint
*/
async function handleToDoListActions(task, method, endpoint) {
let listData;
try {
const accessToken = await getToken();
const data = await callApi(method, endpoint, accessToken, task);
switch (method) {
case 'POST':
listData = JSON.parse(localStorage.getItem('todolist'));
listData = [data, ...listData];
localStorage.setItem('todolist', JSON.stringify(listData));
AddTaskToToDoList(data);
break;
case 'DELETE':
listData = JSON.parse(localStorage.getItem('todolist'));
const index = listData.findIndex((todoItem) => todoItem.id === task.id);
localStorage.setItem('todolist', JSON.stringify([...listData.splice(index, 1)]));
showToDoListItems(listData);
break;
default:
console.log('Unrecognized method.')
break;
}
} catch (error) {
console.error(error);
}
}
/**
* Handles todolist action GET action.
*/
async function getToDos() {
try {
const accessToken = await getToken();
const data = await callApi(
'GET',
protectedResources.toDoListAPI.endpoint,
accessToken
);
if (data) {
localStorage.setItem('todolist', JSON.stringify(data));
showToDoListItems(data);
}
} catch (error) {
console.error(error);
}
}
/**
* Retrieves an access token.
*/
async function getToken() {
let tokenResponse;
if (typeof getTokenPopup === 'function') {
tokenResponse = await getTokenPopup({
scopes: [...protectedResources.toDoListAPI.scopes.read],
redirectUri: '/redirect'
});
} else {
tokenResponse = await getTokenRedirect({
scopes: [...protectedResources.toDoListAPI.scopes.read],
});
}
if (!tokenResponse) {
return null;
}
return tokenResponse.accessToken;
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"AzureAd": {
"Instance": "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/",
"TenantId": "Enter_the_Tenant_Id_Here",
"ClientId": "Enter_the_Application_Id_Here",
"Scopes": {
"Read": ["ToDoList.Read", "ToDoList.ReadWrite"],
"Write": ["ToDoList.ReadWrite"]
},
"AppPermissions": {
"Read": ["ToDoList.Read.All", "ToDoList.ReadWrite.All"],
"Write": ["ToDoList.ReadWrite.All"]
}
},
"https_port": 44351,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
{
"AzureAd": {
"Instance": "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/",
"TenantId": "Enter_the_Tenant_Id_Here",
"ClientId": "Enter_the_Application_Id_Here",
"Scopes": {
"Read": ["ToDoList.Read", "ToDoList.ReadWrite"],
"Write": ["ToDoList.ReadWrite"]
},
"AppPermissions": {
"Read": ["ToDoList.Read.All", "ToDoList.ReadWrite.All"],
"Write": ["ToDoList.ReadWrite.All"]
}
},
"https_port": 44351,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
6 changes: 3 additions & 3 deletions 2-Authorization/3-call-api-node-daemon/App/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# This variable should only be used in the development environment.
# Please remove the variable when moving the app to the production environment.
NODE_TLS_REJECT_UNAUTHORIZED='0'
# This variable should only be used in the development environment.
# Please remove the variable when moving the app to the production environment.
NODE_TLS_REJECT_UNAUTHORIZED='0'
75 changes: 36 additions & 39 deletions 2-Authorization/3-call-api-node-daemon/App/auth.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
const msal = require('@azure/msal-node');

const { msalConfig, protectedResources } = require('./authConfig');

/**
* With client credentials flows permissions need to be granted in the portal by a tenant administrator.
* The scope is always in the format '<resource-appId-uri>/.default'. For more, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
*/
const tokenRequest = {
scopes: [`${protectedResources.apiToDoList.scopes}/.default`],
};

const apiConfig = {
uri: protectedResources.apiToDoList.endpoint,
};



/**
* Initialize a confidential client application. For more info, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/initialize-confidential-client-application.md
*/

const cca = new msal.ConfidentialClientApplication(msalConfig);

/**
* Acquires token with client credentials.
* @param {object} tokenRequest
*/
async function getToken(tokenRequest) {
return await cca.acquireTokenByClientCredential(tokenRequest);
}

module.exports = {
apiConfig: apiConfig,
tokenRequest: tokenRequest,
getToken: getToken,
};
import { ConfidentialClientApplication } from '@azure/msal-node';

import { msalConfig, protectedResources } from './authConfig.js';


/**
* With client credentials flows permissions need to be granted in the portal by a tenant administrator.
* The scope is always in the format '<resource-appId-uri>/.default'. For more, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
*/
export const tokenRequest = {
// scopes: [`${protectedResources.apiToDoList.scope}/.default`], // tried this in case the array format in authConfig was throwing things off.
scopes: [`${protectedResources.apiToDoList.scopes}/.default`],
authority: msalConfig.auth.authority,
// this doesn't help
// skipCache: true,
};

export const apiConfig = {
uri: protectedResources.apiToDoList.endpoint,
};

/**
* Initialize a confidential client application. For more info, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/initialize-confidential-client-application.md
*/

const cca = new ConfidentialClientApplication(msalConfig);

/**
* Acquires token with client credentials.
* @param {object} tokenRequest
*/
export async function getToken(tokenRequest) {
return await cca.acquireTokenByClientCredential(tokenRequest);
}
Loading