- Wallet needs a public did (for connectionless present-proof requests)
+ Wallet needs a public did (for connection-less present-proof requests)
@@ -31,13 +31,9 @@
Navigate to the controller
- swagger and POST to
+ swagger and POST to
'/ver_configs' with the default payload
-
- Click "Login" in the top right, then click "Verifiable Credential
- Access"
-
diff --git a/demo/vue/app/frontend/tests/unit/App.spec.js b/demo/vue/app/frontend/tests/unit/App.spec.js
deleted file mode 100644
index 4e68e9b0..00000000
--- a/demo/vue/app/frontend/tests/unit/App.spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-
-import Secure from '@/App.vue';
-
-describe('Secure.vue', () => {
- let vuetify;
-
- beforeEach(() => {
- vuetify = new Vuetify();
- });
-
- it('renders', () => {
- const wrapper = shallowMount(Secure, {
- vuetify,
- stubs: ['BaseSecure', 'BCGovFooter', 'BCGovHeader', 'BCGovNavBar', 'router-view']
- });
-
- expect(wrapper.text()).toMatch('');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/HelloCall.spec.js b/demo/vue/app/frontend/tests/unit/components/HelloCall.spec.js
deleted file mode 100644
index 506add6f..00000000
--- a/demo/vue/app/frontend/tests/unit/components/HelloCall.spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import HelloCall from '@/components/HelloCall.vue';
-import helloService from '@/services/helloService';
-
-describe('HelloCall.vue', () => {
- const getHelloSpy = jest.spyOn(helloService, 'getHello');
-
- beforeEach(() => {
- getHelloSpy.mockReset();
- });
-
- it('renders the page', () => {
- const wrapper = shallowMount(HelloCall, { stubs: ['BaseDialog'] });
- expect(wrapper.text()).toMatch('Get Response');
- });
-
- it('renders a success dialog on click', async () => {
- getHelloSpy.mockResolvedValue('test');
-
- const wrapper = shallowMount(HelloCall, { stubs: ['BaseDialog'] });
- await wrapper.vm.getHello();
-
- expect(wrapper.text()).toMatch('Get Response');
- expect(wrapper.vm.error).toBeFalsy();
- expect(wrapper.vm.showDialog).toBeTruthy();
- });
-
- it('renders a failure dialog on click', async () => {
- getHelloSpy.mockRejectedValue('test');
-
- const wrapper = shallowMount(HelloCall, { stubs: ['BaseDialog'] });
- await wrapper.vm.getHello();
-
- expect(wrapper.text()).toMatch('Get Response');
- expect(wrapper.vm.error).toBeTruthy();
- expect(wrapper.vm.showDialog).toBeTruthy();
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/HelloWorld.spec.js b/demo/vue/app/frontend/tests/unit/components/HelloWorld.spec.js
deleted file mode 100644
index 3c9e1733..00000000
--- a/demo/vue/app/frontend/tests/unit/components/HelloWorld.spec.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import HelloWorld from '@/components/HelloWorld.vue';
-
-describe('HelloWorld.vue', () => {
- it('renders', () => {
- const wrapper = shallowMount(HelloWorld);
- expect(wrapper.text()).toMatch('Vuetify');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/base/BaseAuthButton.spec.js b/demo/vue/app/frontend/tests/unit/components/base/BaseAuthButton.spec.js
deleted file mode 100644
index 8843c74f..00000000
--- a/demo/vue/app/frontend/tests/unit/components/base/BaseAuthButton.spec.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-
-import getRouter from '@/router';
-import BaseAuthButton from '@/components/base/BaseAuthButton.vue';
-
-const router = getRouter();
-const localVue = createLocalVue();
-localVue.use(router);
-localVue.use(Vuex);
-
-describe('BaseAuthButton.vue', () => {
- const { location } = window;
- const mockReplace = jest.fn(cb => {
- cb();
- });
- let store;
-
- beforeAll(() => {
- delete window.location;
- window.location = {
- pathname: '/',
- replace: mockReplace
- };
- });
-
- beforeEach(() => {
- mockReplace.mockReset();
- store = new Vuex.Store();
- });
-
- afterAll(() => {
- window.location = location;
- });
-
- it('renders nothing when not authenticated and does not hasLogin', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseAuthButton, { localVue, router, store });
-
- expect(wrapper.text()).toEqual('');
- });
-
- it('renders login when not authenticated and hasLogin', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseAuthButton, { localVue, router, store });
- wrapper.vm.$route.meta.hasLogin = true;
-
- expect(wrapper.text()).toMatch('Login');
- });
-
- it('renders logout when authenticated', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => true,
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseAuthButton, { localVue, router, store });
-
- expect(wrapper.text()).toMatch('Logout');
- });
-
- it('renders nothing if keycloak is not keycloakReady', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- keycloakReady: () => false
- }
- });
-
- const wrapper = shallowMount(BaseAuthButton, { localVue, router, store });
-
- expect(wrapper.text()).toBeFalsy();
- });
-
- it('login button redirects to login url', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- createLoginUrl: () => () => 'test',
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseAuthButton, { localVue, router, store });
- wrapper.vm.login();
-
- expect(wrapper.text()).toMatch('Login');
- expect(mockReplace).toHaveBeenCalledTimes(1);
- });
-
- it('logout button redirects to logout url', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => true,
- createLogoutUrl: () => () => 'test',
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseAuthButton, {
- localVue, router, store, mocks: {
- $config: {
- basePath: 'test'
- }
- }
- });
- wrapper.vm.logout();
-
- expect(wrapper.text()).toMatch('Logout');
- expect(mockReplace).toHaveBeenCalledTimes(1);
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/base/BaseDialog.spec.js b/demo/vue/app/frontend/tests/unit/components/base/BaseDialog.spec.js
deleted file mode 100644
index 6960d65c..00000000
--- a/demo/vue/app/frontend/tests/unit/components/base/BaseDialog.spec.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-
-import BaseDialog from '@/components/base/BaseDialog.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuetify);
-
-describe('BaseDialog.vue', () => {
- it('renders with ok button', async () => {
- const wrapper = shallowMount(BaseDialog, { localVue });
- await wrapper.vm.closeDialog();
- await localVue.nextTick();
-
- expect(wrapper.text()).toMatch('OK');
- });
-
- it('renders with continue button', async () => {
- const wrapper = shallowMount(BaseDialog, {
- localVue,
- propsData: { type: 'CONTINUE' }
- });
- await wrapper.vm.continueDialog();
- await localVue.nextTick();
-
- expect(wrapper.text()).toMatch('Continue');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/base/BaseSecure.spec.js b/demo/vue/app/frontend/tests/unit/components/base/BaseSecure.spec.js
deleted file mode 100644
index b3921bee..00000000
--- a/demo/vue/app/frontend/tests/unit/components/base/BaseSecure.spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-
-import BaseSecure from '@/components/base/BaseSecure.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('BaseSecure.vue', () => {
- const { location } = window;
- const mockReplace = jest.fn(cb => {
- cb();
- });
- let store;
-
- beforeAll(() => {
- delete window.location;
- window.location = {
- replace: mockReplace
- };
- });
-
- beforeEach(() => {
- mockReplace.mockReset();
- store = new Vuex.Store();
- });
-
- afterAll(() => {
- window.location = location;
- });
-
- it('renders nothing if authenticated and authorized', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => true,
- hasResourceRoles: () => () => true,
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseSecure, { localVue, store });
-
- expect(wrapper.text()).toMatch('');
- });
-
- it('renders a message if authenticated and unauthorized', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => true,
- hasResourceRoles: () => () => false,
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseSecure, {
- localVue,
- propsData: {
- admin: true
- },
- store,
- stubs: ['router-link']
- });
-
- expect(wrapper.text()).toMatch('You are not authorized to use this feature.');
- });
-
- it('renders a message with login button if unauthenticated', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- hasResourceRoles: () => () => false,
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseSecure, { localVue, store });
-
- expect(wrapper.text()).toMatch('You must be logged in to use this feature.');
- });
-
- it('renders a message without login button if unauthenticated', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- hasResourceRoles: () => () => false,
- keycloakReady: () => false
- }
- });
-
- const wrapper = shallowMount(BaseSecure, { localVue, store });
-
- expect(wrapper.text()).toMatch('You must be logged in to use this feature.');
- });
-
- it('login button redirects to login url', () => {
- store.registerModule('auth', {
- namespaced: true,
- getters: {
- authenticated: () => false,
- createLoginUrl: () => () => 'test',
- keycloakReady: () => true
- }
- });
-
- const wrapper = shallowMount(BaseSecure, { localVue, store });
- wrapper.vm.login();
-
- expect(wrapper.text()).toMatch('Login');
- expect(mockReplace).toHaveBeenCalledTimes(1);
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovFooter.spec.js b/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovFooter.spec.js
deleted file mode 100644
index 44ba1666..00000000
--- a/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovFooter.spec.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import BCGovFooter from '@/components/bcgov/BCGovFooter.vue';
-
-describe('BCGovFooter.vue', () => {
- it('renders', () => {
- const wrapper = shallowMount(BCGovFooter);
- expect(wrapper.text()).toMatch('About gov.bc.ca');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovHeader.spec.js b/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovHeader.spec.js
deleted file mode 100644
index d539537a..00000000
--- a/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovHeader.spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-
-import BCGovHeader from '@/components/bcgov/BCGovHeader.vue';
-
-describe('BCGovHeader.vue', () => {
- let vuetify;
-
- beforeEach(() => {
- vuetify = new Vuetify();
- });
-
- it('renders', () => {
- const wrapper = shallowMount(BCGovHeader, {
- vuetify,
- stubs: ['BaseAuthButton']
- });
-
- expect(wrapper.text()).toMatch('');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovNavBar.spec.js b/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovNavBar.spec.js
deleted file mode 100644
index 2f6c83cc..00000000
--- a/demo/vue/app/frontend/tests/unit/components/bcgov/BCGovNavBar.spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-import VueRouter from 'vue-router';
-
-import BCGovNavBar from '@/components/bcgov/BCGovNavBar.vue';
-
-describe('BCGovNavBar.vue', () => {
- let router;
- let vuetify;
-
- beforeEach(() => {
- router = new VueRouter();
- vuetify = new Vuetify();
- });
-
- it('renders', () => {
- const wrapper = shallowMount(BCGovNavBar, {
- vuetify,
- router,
- stubs: ['router-link', 'router-view']
- });
-
- expect(wrapper.text()).toContain('Home');
- expect(wrapper.text()).toContain('Secure');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/globalSetup.js b/demo/vue/app/frontend/tests/unit/globalSetup.js
deleted file mode 100644
index aedef2c8..00000000
--- a/demo/vue/app/frontend/tests/unit/globalSetup.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import Vue from 'vue';
-import Vuetify from 'vuetify';
-
-Vue.use(Vuetify);
diff --git a/demo/vue/app/frontend/tests/unit/router/index.spec.js b/demo/vue/app/frontend/tests/unit/router/index.spec.js
deleted file mode 100644
index fbbe7454..00000000
--- a/demo/vue/app/frontend/tests/unit/router/index.spec.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import getRouter from '@/router';
-
-describe('Router', () => {
- const router = getRouter();
- const routes = router.options.routes;
-
- it('has the correct number of routes', () => {
- expect(routes).toHaveLength(4);
- });
-
- it('has the expected routes', () => {
- const routeSet = new Set(routes);
- expect(routeSet).toContainEqual(expect.objectContaining({ name: 'Home' }));
- expect(routeSet).toContainEqual(expect.objectContaining({ name: 'Secure' }));
- expect(routeSet).toContainEqual(expect.objectContaining({ name: 'NotFound' }));
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/services/helloService.spec.js b/demo/vue/app/frontend/tests/unit/services/helloService.spec.js
deleted file mode 100644
index 24c6538f..00000000
--- a/demo/vue/app/frontend/tests/unit/services/helloService.spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-
-import helloService from '@/services/helloService';
-import { ApiRoutes } from '@/utils/constants';
-
-const mockInstance = axios.create();
-
-jest.mock('@/services/interceptors', () => {
- return {
- appAxios: () => mockInstance
- };
-});
-
-describe('getHello', () => {
- const mockAxios = new MockAdapter(mockInstance);
-
- beforeEach(() => {
- mockAxios.reset();
- });
-
- it('calls email endpoint', async () => {
- mockAxios.onGet(ApiRoutes.HELLO).reply(200, 'ok');
-
- const result = await helloService.getHello();
- expect(result).toBeTruthy();
- expect(result.data).toEqual('ok');
- expect(mockAxios.history.get.length).toBe(1);
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/store/index.spec.js b/demo/vue/app/frontend/tests/unit/store/index.spec.js
deleted file mode 100644
index dc18fa0d..00000000
--- a/demo/vue/app/frontend/tests/unit/store/index.spec.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import index from '@/store/index';
-
-describe('index.js', () => {
-
- it('exists', () => {
- expect(index.getters).toBeTruthy();
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/store/modules/auth.actions.spec.js b/demo/vue/app/frontend/tests/unit/store/modules/auth.actions.spec.js
deleted file mode 100644
index 9232a2cd..00000000
--- a/demo/vue/app/frontend/tests/unit/store/modules/auth.actions.spec.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import { cloneDeep } from 'lodash';
-import Vue from 'vue';
-
-import store from '@/store/modules/auth';
-
-describe('auth actions', () => {
- const { location } = window;
- const mockReplace = jest.fn(cb => {
- cb();
- });
- const mockStore = {
- commit: jest.fn(),
- getters: {
- createLoginUrl: jest.fn(),
- createLogoutUrl: jest.fn()
- },
- rootGetters: {},
- state: cloneDeep(store.state)
- };
-
- beforeAll(() => {
- delete window.location;
- window.location = {
- pathname: '/',
- replace: mockReplace
- };
- Vue.prototype.$config = { basePath: 'test' };
- });
-
- beforeEach(() => {
- Object.keys(mockStore).forEach((f) => {
- if (jest.isMockFunction(f)) f.mockReset();
- });
- mockStore.state = cloneDeep(store.state);
- });
-
- afterAll(() => {
- window.location = location;
- Vue.prototype.$config = undefined;
- });
-
- describe('login', () => {
- beforeEach(() => {
- mockStore.commit.mockReset();
- mockStore.getters.createLoginUrl.mockReset();
- delete mockStore.getters.keycloakReady;
- delete mockStore.getters.redirectUri;
- mockReplace.mockReset();
- });
-
- it('should do nothing if keycloak is not ready', () => {
- mockStore.getters.keycloakReady = false;
- store.actions.login(mockStore);
-
- expect(mockStore.commit).toHaveBeenCalledTimes(0);
- expect(window.location.replace).toHaveBeenCalledTimes(0);
- expect(mockStore.getters.createLoginUrl).toHaveBeenCalledTimes(0);
- });
-
- it('should update redirectUri if not defined', () => {
- mockStore.getters.keycloakReady = true;
- mockStore.getters.redirectUri = undefined;
-
- store.actions.login(mockStore, 'test');
-
- expect(mockStore.commit).toHaveBeenCalledTimes(1);
- expect(window.location.replace).toHaveBeenCalledTimes(1);
- expect(mockStore.getters.createLoginUrl).toHaveBeenCalledTimes(1);
- });
-
- it('should update redirectUri if already defined', () => {
- mockStore.getters.keycloakReady = true;
- mockStore.getters.redirectUri = 'value';
-
- store.actions.login(mockStore, 'test');
-
- expect(mockStore.commit).toHaveBeenCalledTimes(0);
- expect(window.location.replace).toHaveBeenCalledTimes(1);
- expect(mockStore.getters.createLoginUrl).toHaveBeenCalledTimes(1);
- });
-
- it('should navigate with provided options', () => {
- mockStore.getters.keycloakReady = true;
- mockStore.getters.redirectUri = 'value';
-
- store.actions.login(mockStore, 'test');
-
- expect(mockStore.commit).toHaveBeenCalledTimes(0);
- expect(window.location.replace).toHaveBeenCalledTimes(1);
- expect(mockStore.getters.createLoginUrl).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('logout', () => {
- beforeEach(() => {
- mockStore.getters.createLogoutUrl.mockReset();
- delete mockStore.getters.keycloakReady;
- mockReplace.mockReset();
- });
-
- it('should do nothing if keycloak is not ready', () => {
- mockStore.getters.keycloakReady = false;
- store.actions.logout(mockStore);
-
- expect(window.location.replace).toHaveBeenCalledTimes(0);
- expect(mockStore.getters.createLogoutUrl).toHaveBeenCalledTimes(0);
- });
-
- it('should trigger navigation action if keycloak is ready', () => {
- mockStore.getters.keycloakReady = true;
- store.actions.logout(mockStore);
-
- expect(window.location.replace).toHaveBeenCalledTimes(1);
- expect(mockStore.getters.createLogoutUrl).toHaveBeenCalledTimes(1);
- });
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/store/modules/auth.getters.spec.js b/demo/vue/app/frontend/tests/unit/store/modules/auth.getters.spec.js
deleted file mode 100644
index e9b9b7c0..00000000
--- a/demo/vue/app/frontend/tests/unit/store/modules/auth.getters.spec.js
+++ /dev/null
@@ -1,195 +0,0 @@
-import { cloneDeep } from 'lodash';
-import { createLocalVue } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
-
-import authStore from '@/store/modules/auth';
-import { AppRoles } from '@/utils/constants';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-const zeroUuid = '00000000-0000-0000-0000-000000000000';
-
-const keycloakHelper = (mockKcObject) => {
- // TODO: Find better way to set up keycloak object mock without deleting first
- if (Vue.prototype.$keycloak) {
- delete Vue.prototype.$keycloak;
- }
- Object.defineProperty(Vue.prototype, '$keycloak', {
- configurable: true, // Needed to allow deletions later
- get() {
- return mockKcObject;
- }
- });
-};
-
-describe('auth getters', () => {
- let authenticated;
- let roles;
- let store;
-
- beforeEach(() => {
- authenticated = true;
- roles = [];
- store = new Vuex.Store(cloneDeep(authStore));
-
- Object.defineProperty(Vue.prototype, '$keycloak', {
- configurable: true, // Needed to allow deletions later
- get() {
- return {
- authenticated: authenticated,
- createLoginUrl: () => 'loginUrl',
- createLogoutUrl: () => 'logoutUrl',
- fullName: 'fName',
- ready: true,
- subject: zeroUuid,
- token: 'token',
- tokenParsed: {
- email: 'e@mail.com',
- identity_provider: 'idir',
- realm_access: {},
- resource_access: {
- app: {
- roles: roles
- }
- }
- },
- userName: 'uName'
- };
- }
- });
- });
-
- afterEach(() => {
- if (Vue.prototype.$keycloak) {
- delete Vue.prototype.$keycloak;
- }
- });
-
- it('authenticated should return a boolean', () => {
- expect(store.getters.authenticated).toBeTruthy();
- });
-
- it('createLoginUrl should return a string', () => {
- expect(store.getters.createLoginUrl).toBeTruthy();
- expect(typeof store.getters.createLoginUrl).toBe('function');
- expect(store.getters.createLoginUrl()).toMatch('loginUrl');
- });
-
- it('createLogoutUrl should return a string', () => {
- expect(store.getters.createLogoutUrl).toBeTruthy();
- expect(typeof store.getters.createLogoutUrl).toBe('function');
- expect(store.getters.createLogoutUrl()).toMatch('logoutUrl');
- });
-
- it('email should return a string', () => {
- expect(store.getters.email).toBeTruthy();
- expect(store.getters.email).toMatch('e@mail.com');
- });
-
- it('email should return an empty string', () => {
- keycloakHelper({
- tokenParsed: undefined
- });
-
- expect(store.getters.email).toBeFalsy();
- expect(store.getters.email).toEqual('');
- });
-
- it('fullName should return a string', () => {
- expect(store.getters.fullName).toBeTruthy();
- expect(store.getters.fullName).toMatch('fName');
- });
-
- it('hasResourceRoles should return false if unauthenticated', () => {
- authenticated = false;
-
- expect(store.getters.authenticated).toBeFalsy();
- expect(store.getters.hasResourceRoles('app', roles)).toBeFalsy();
- });
-
- it('hasResourceRoles should return true when checking no roles', () => {
- authenticated = true;
- roles = [];
-
- expect(store.getters.authenticated).toBeTruthy();
- expect(store.getters.hasResourceRoles('app', roles)).toBeTruthy();
- });
-
- it('hasResourceRoles should return true when role exists', () => {
- authenticated = true;
- roles = [AppRoles.TESTROLE];
-
- expect(store.getters.authenticated).toBeTruthy();
- expect(store.getters.hasResourceRoles('app', roles)).toBeTruthy();
- });
-
- it('hasResourceRoles should return false when resource does not exist', () => {
- authenticated = true;
- roles = ['non-existent-role'];
-
- keycloakHelper({
- authenticated: authenticated,
- tokenParsed: {
- realm_access: {},
- resource_access: {}
- }
- });
-
- expect(store.getters.authenticated).toBeTruthy();
- expect(store.getters.hasResourceRoles('app', roles)).toBeFalsy();
- });
-
- it('identityProvider should return a string', () => {
- expect(store.getters.identityProvider).toBeTruthy();
- expect(typeof store.getters.identityProvider).toBe('string');
- });
-
- it('keycloakReady should return a boolean', () => {
- expect(store.getters.keycloakReady).toBeTruthy();
- });
-
- it('keycloakSubject should return a string', () => {
- expect(store.getters.keycloakSubject).toBeTruthy();
- expect(store.getters.keycloakSubject).toMatch(zeroUuid);
- });
-
- it('moduleLoaded should return a boolean', () => {
- expect(store.getters.moduleLoaded).toBeTruthy();
- });
-
- it('realmAccess should return an object', () => {
- expect(store.getters.realmAccess).toBeTruthy();
- expect(typeof store.getters.realmAccess).toBe('object');
- });
-
- it('realmAccess should return a string', () => {
- const uri = 'http://foo.bar';
- store.replaceState({ redirectUri: uri });
-
- expect(store.getters.redirectUri).toBeTruthy();
- expect(typeof store.getters.redirectUri).toBe('string');
- expect(store.getters.redirectUri).toEqual(uri);
- });
-
- it('resourceAccess should return an object', () => {
- expect(store.getters.resourceAccess).toBeTruthy();
- expect(typeof store.getters.resourceAccess).toBe('object');
- });
-
- it('token should return a string', () => {
- expect(store.getters.token).toBeTruthy();
- expect(store.getters.token).toMatch('token');
- });
-
- it('tokenParsed should return an object', () => {
- expect(store.getters.tokenParsed).toBeTruthy();
- expect(typeof store.getters.tokenParsed).toBe('object');
- });
-
- it('userName should return a string', () => {
- expect(store.getters.userName).toBeTruthy();
- expect(store.getters.userName).toMatch('uName');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/store/modules/auth.mutations.spec.js b/demo/vue/app/frontend/tests/unit/store/modules/auth.mutations.spec.js
deleted file mode 100644
index 6bd72c22..00000000
--- a/demo/vue/app/frontend/tests/unit/store/modules/auth.mutations.spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { cloneDeep } from 'lodash';
-
-import store from '@/store/modules/auth';
-
-describe('auth mutations', () => {
- let state;
-
- beforeEach(() => {
- state = cloneDeep(store.state);
- });
-
- it('SET_REDIRECTURI should update redirecturi', () => {
- const uri = 'http://foo.bar';
- store.mutations.SET_REDIRECTURI(state, uri);
-
- expect(state.redirectUri).toBeTruthy();
- expect(state.redirectUri).toEqual(uri);
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/views/Home.spec.js b/demo/vue/app/frontend/tests/unit/views/Home.spec.js
deleted file mode 100644
index ccebeaff..00000000
--- a/demo/vue/app/frontend/tests/unit/views/Home.spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-
-import Home from '@/views/Home.vue';
-
-describe('Home.vue', () => {
- let vuetify;
-
- beforeEach(() => {
- vuetify = new Vuetify();
- });
-
- it('renders', () => {
- const wrapper = shallowMount(Home, {
- vuetify,
- stubs: ['HelloWorld']
- });
-
- expect(wrapper.html()).toMatch('Welcome to Vuetify');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/views/NotFound.spec.js b/demo/vue/app/frontend/tests/unit/views/NotFound.spec.js
deleted file mode 100644
index 923846b3..00000000
--- a/demo/vue/app/frontend/tests/unit/views/NotFound.spec.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-import VueRouter from 'vue-router';
-
-import NotFound from '@/views/NotFound.vue';
-
-describe('NotFound.vue', () => {
- let router;
- let vuetify;
-
- beforeEach(() => {
- router = new VueRouter();
- vuetify = new Vuetify();
- });
-
- it('renders', () => {
- const wrapper = shallowMount(NotFound, {
- vuetify,
- router,
- stubs: ['router-link', 'router-view']
- });
-
- expect(wrapper.text()).toMatch('404: Page not found. :(');
- });
-});
diff --git a/demo/vue/app/frontend/tests/unit/views/Secure.spec.js b/demo/vue/app/frontend/tests/unit/views/Secure.spec.js
deleted file mode 100644
index e8489474..00000000
--- a/demo/vue/app/frontend/tests/unit/views/Secure.spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vuetify from 'vuetify';
-
-import Secure from '@/views/Secure.vue';
-
-describe('Secure.vue', () => {
- let vuetify;
-
- beforeEach(() => {
- vuetify = new Vuetify();
- });
-
- it('renders', () => {
- const wrapper = shallowMount(Secure, {
- vuetify,
- stubs: ['BaseSecure']
- });
-
- expect(wrapper.text()).toMatch('');
- });
-});
diff --git a/demo/vue/app/package-lock.json b/demo/vue/app/package-lock.json
index 4e1baee5..e66e2310 100644
--- a/demo/vue/app/package-lock.json
+++ b/demo/vue/app/package-lock.json
@@ -2667,9 +2667,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
@@ -3190,9 +3190,9 @@
"dev": true
},
"node_modules/eslint-config-esnext/node_modules/cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
+ "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"dev": true,
"dependencies": {
"nice-try": "^1.0.4",
@@ -3658,9 +3658,9 @@
"dev": true
},
"node_modules/eslint-config-node/node_modules/cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
+ "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"dev": true,
"dependencies": {
"nice-try": "^1.0.4",
@@ -4128,9 +4128,9 @@
"dev": true
},
"node_modules/eslint-config-react-native/node_modules/cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
+ "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"dev": true,
"dependencies": {
"nice-try": "^1.0.4",
@@ -4611,9 +4611,9 @@
"dev": true
},
"node_modules/eslint-config-recommended/node_modules/cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
+ "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"dev": true,
"dependencies": {
"nice-try": "^1.0.4",
diff --git a/demo/vue/app/src/components/cdogsService.js b/demo/vue/app/src/components/cdogsService.js
deleted file mode 100644
index 9d047286..00000000
--- a/demo/vue/app/src/components/cdogsService.js
+++ /dev/null
@@ -1,144 +0,0 @@
-const config = require('config');
-const crypto = require('crypto');
-const FormData = require('form-data');
-const fs = require('fs-extra');
-
-const ClientConnection = require('./clientConnection');
-const errorToProblem = require('./errorToProblem');
-const log = require('./log')(module.filename);
-
-const SERVICE = 'CDOGS';
-
-class CdogsService {
- constructor({ tokenUrl, clientId, clientSecret, apiUrl }) {
- log.verbose(`Constructed with ${tokenUrl}, ${clientId}, clientSecret, ${apiUrl}`, { function: 'constructor' });
- if (!tokenUrl || !clientId || !clientSecret || !apiUrl) {
- log.error('Invalid configuration.', { function: 'constructor' });
- throw new Error('CdogsService is not configured. Check configuration.');
- }
- this.connection = new ClientConnection({ tokenUrl, clientId, clientSecret });
- this.axios = this.connection.axios;
- this.apiUrl = apiUrl;
- this.apiV2 = `${this.apiUrl}/v2`;
- }
-
- async health() {
- try {
- const url = `${this.apiV2}/health`;
- log.debug(`GET to ${url}`, { function: 'health' });
-
- const { data, status } = await this.axios.get(url, {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
-
- return { data, status };
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async templateUploadAndRender(body) {
- try {
- const url = `${this.apiV2}/template/render`;
- log.debug(`POST to ${url}`, { function: 'templateUploadAndRender' });
-
- const { data, headers, status } = await this.axios.post(url, body, {
- responseType: 'arraybuffer' // Needed for binaries unless you want pain
- });
-
- return { data, headers, status };
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async templateRender(templateId, body) {
- try {
- const url = `${this.apiV2}/template/${templateId}/render`;
- log.debug(`POST to ${url}`, { function: 'templateRender' });
-
- const { data, headers, status } = await this.axios.post(url, body, {
- headers: {
- 'content-type': 'application/json'
- },
- responseType: 'arraybuffer'
- });
-
- return { data, headers, status };
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async getTemplate(templateId) {
- try {
- const url = `${this.apiV2}/template/${templateId}`;
- log.debug(`GET to ${url}`, { function: 'getTemplate' });
-
- const { data, status } = await this.axios.get(url, {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
-
- return { data, status };
- } catch (e) {
- if (e.response && e.response.status === 404) {
- return { data: 'Not Found', status: 404 };
- }
- errorToProblem(SERVICE, e);
- }
- }
-
- async uploadTemplate(path) {
- try {
- const form = new FormData();
- form.append('template', fs.createReadStream(path));
-
- const url = `${this.apiV2}/template`;
- log.debug(`POST to ${url}`, { function: 'uploadTemplate' });
-
- const { data, headers, status } = await this.axios(
- {
- method: 'post',
- url: url,
- data: form,
- headers: {
- 'content-type': `multipart/form-data; boundary=${form._boundary}`,
- },
- }
- );
-
- return { data, headers, status };
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async getHash(file) {
- const hash = crypto.createHash('sha256');
- const stream = fs.createReadStream(file);
- return new Promise((resolve, reject) => {
- stream.on('readable', () => {
- let chunk;
- while (null !== (chunk = stream.read())) {
- hash.update(chunk);
- }
- });
- stream.on('end', () => resolve(hash.digest('hex')));
- stream.on('error', error => reject(error));
- });
- }
-
-
-}
-
-const endpoint = config.get('serviceClient.commonServices.cdogs.endpoint');
-const tokenEndpoint = config.get('serviceClient.commonServices.tokenEndpoint');
-const username = config.get('serviceClient.commonServices.username');
-const password = config.get('serviceClient.commonServices.password');
-
-let cdogsService = new CdogsService({tokenUrl: tokenEndpoint, clientId: username, clientSecret: password, apiUrl: endpoint});
-module.exports = cdogsService;
diff --git a/demo/vue/app/src/components/chesService.js b/demo/vue/app/src/components/chesService.js
deleted file mode 100644
index a7b5d932..00000000
--- a/demo/vue/app/src/components/chesService.js
+++ /dev/null
@@ -1,154 +0,0 @@
-const config = require('config');
-
-const ClientConnection = require('./clientConnection');
-const errorToProblem = require('./errorToProblem');
-const log = require('./log')(module.filename);
-
-const SERVICE = 'CHES';
-
-class ChesService {
- constructor({tokenUrl, clientId, clientSecret, apiUrl}) {
- log.verbose(`Constructed with ${tokenUrl}, ${clientId}, clientSecret, ${apiUrl}`, { function: 'constructor' });
- if (!tokenUrl || !clientId || !clientSecret || !apiUrl) {
- log.error('Invalid configuration.', { function: 'constructor' });
- throw new Error('ChesService is not configured. Check configuration.');
- }
- this.connection = new ClientConnection({ tokenUrl, clientId, clientSecret });
- this.axios = this.connection.axios;
- this.apiUrl = apiUrl;
- this.apiV1 = `${this.apiUrl}/v1`;
- }
-
- async health() {
- try {
- const response = await this.axios.get(
- `${this.apiV1}/health`,
- {
- headers: {
- 'Content-Type': 'application/json'
- }
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async statusQuery(params) {
- try {
- const response = await this.axios.get(
- `${this.apiV1}/status`,
- {
- params: params,
- headers: {
- 'Content-Type': 'application/json'
- }
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async cancelMsg(msgId) {
- try {
- const response = await this.axios.delete(
- `${this.apiV1}/cancel/${msgId}`,
- {
- headers: {
- 'Content-Type': 'application/json'
- }
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async cancelQuery(params) {
- try {
- const response = await this.axios.delete(
- `${this.apiV1}/cancel`,
- {
- params: params,
- headers: {
- 'Content-Type': 'application/json'
- }
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async send(email) {
- try {
- const response = await this.axios.post(
- `${this.apiV1}/email`,
- email,
- {
- headers: {
- 'Content-Type': 'application/json'
- },
- maxContentLength: Infinity,
- maxBodyLength: Infinity
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
-
- async merge(data) {
- try {
- const response = await this.axios.post(
- `${this.apiV1}/emailMerge`,
- data,
- {
- headers: {
- 'Content-Type': 'application/json'
- },
- maxContentLength: Infinity,
- maxBodyLength: Infinity
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
- async preview(data) {
- try {
- const response = await this.axios.post(
- `${this.apiV1}/emailMerge/preview`,
- data,
- {
- headers: {
- 'Content-Type': 'application/json'
- },
- maxContentLength: Infinity,
- maxBodyLength: Infinity
- }
- );
- return response.data;
- } catch (e) {
- errorToProblem(SERVICE, e);
- }
- }
-
-}
-
-const endpoint = config.get('serviceClient.commonServices.ches.endpoint');
-const tokenEndpoint = config.get('serviceClient.commonServices.tokenEndpoint');
-const username = config.get('serviceClient.commonServices.username');
-const password = config.get('serviceClient.commonServices.password');
-
-let chesService = new ChesService({tokenUrl: tokenEndpoint, clientId: username, clientSecret: password, apiUrl: endpoint});
-module.exports = chesService;
diff --git a/demo/vue/docker-compose.yaml b/demo/vue/docker-compose.yaml
index 76c96eff..ad9fab82 100644
--- a/demo/vue/docker-compose.yaml
+++ b/demo/vue/docker-compose.yaml
@@ -7,7 +7,7 @@ services:
build: .
command: npm run serve
environment:
- FRONTEND_KC_PRES_REQ_CONF_ID: showcase-person
+ FRONTEND_KC_PRES_REQ_CONF_ID: test-proof
FRONTEND_KC_SERVERURL: "http://localhost:8880/auth"
FRONTEND_KC_REALM: "vc-authn"
FRONTEND_KC_CLIENTID: "vue-fe"
diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml
index f875e1fb..cadf5a7a 100644
--- a/docker/docker-compose.yaml
+++ b/docker/docker-compose.yaml
@@ -1,7 +1,7 @@
version: "3"
services:
controller:
- image: vc-authn-oidc-controller
+ image: acapy-vc-authn-oidc-controller
entrypoint: /bin/bash
command: >
-c "
diff --git a/docker/manage b/docker/manage
index a8472c20..8f87050a 100755
--- a/docker/manage
+++ b/docker/manage
@@ -107,7 +107,7 @@ build-oidc-controller() {
#
echo -e "\nBuilding oidc-controller image..."
docker build \
- -t 'vc-authn-oidc-controller' \
+ -t 'acapy-vc-authn-oidc-controller' \
-f './oidc-controller/Dockerfile' '..'
}
diff --git a/docs/BestPractices.md b/docs/BestPractices.md
index f8330bf3..07622d19 100644
--- a/docs/BestPractices.md
+++ b/docs/BestPractices.md
@@ -1,18 +1,18 @@
# VC AuthN Best Practices
-This document is intended as a list of best practices and recommendations that are applicable when using `vc-authn-oidc` as means of authorization provider for web applications.
+This document is intended as a list of best practices and recommendations that are applicable when using `acapy-vc-authn-oidc` as means of authorization provider for web applications.
## Ensure the response for the right proof was received
-When using `vc-authn-oidc` to secure a web application, the request to the identity provider must include a `pres_req_conf_id` query parameter set to the id of the `vc-authn-oidc` configuration that must be used to authenticate with the Identity Provider.
+When using `acapy-vc-authn-oidc` to secure a web application, the request to the identity provider must include a `pres_req_conf_id` query parameter set to the id of the `acapy-vc-authn-oidc` configuration that must be used to authenticate with the Identity Provider.
The query parameter - however - can be changed dynamically: this is a desired behaviour, as it allows web applications to dynamically request the proof-request for the circumstance/scenario that is more appropriate.
-Similarly to checking a user's roles, when an id token is received from vc-authn the application should check that the value of the `pres_req_conf_id` attribute on the id token matches the value of the query parameter submitted to the IdP in the first place. If this is not the case, the user authentication may have been successful, but it did not satisfy the initial requirements (another example could be a web application that allows authentication using multiple Identity Providers, but only one of those is authorized to provide extended privileges to the user).
+Similarly to checking a user's roles, when an id token is received from `acapy-vc-authn-oidc` the application should check that the value of the `pres_req_conf_id` attribute on the id token matches the value of the query parameter submitted to the IdP in the first place. If this is not the case, the user authentication may have been successful, but it did not satisfy the initial requirements (another example could be a web application that allows authentication using multiple Identity Providers, but only one of those is authorized to provide extended privileges to the user).
## Consume the claims produced by the proof-request
-Starting with `v2.0.0`, claims populated by values provided in a proof-request are no longer individually added to the root of the JWT issued by VC-AuthN. This decision was made to limit the number of attribute mappers required in systems with more than one proof-request configuration available for relying parties to consume when authenticating.
+Starting with `v2.0.0`, claims populated by values provided in a proof-request are no longer individually added to the root of the JWT issued by ACAPy VC-AuthN. This decision was made to limit the number of attribute mappers required in systems with more than one proof-request configuration available for relying parties to consume when authenticating.
Instead, all claims are packaged in the `vc_presented_attributes` returned at the root of the JWT. Example:
diff --git a/docs/ConfigurationGuide.md b/docs/ConfigurationGuide.md
index 652f7f70..69160485 100644
--- a/docs/ConfigurationGuide.md
+++ b/docs/ConfigurationGuide.md
@@ -15,7 +15,7 @@ The first step is to add VC Authn as a new Identity Provider for our AIM system.
3. We will now configure the Open Id Connect parameters for our new provider.
[!NOTE]
-VC-AuthN exposes the `.well-known/openid-configuration` endpoint to provide systems that support it automatic discovery of the endpoints and features of the Identity Provider. If you decide to do so, switch on **Use discovery endpoint** and enter `{VC_AUTHN_PUBLIC_URL}/.well-known/openid-configuration` to proceed.
+ACAPy VC-AuthN exposes the `.well-known/openid-configuration` endpoint to provide systems that support it automatic discovery of the endpoints and features of the Identity Provider. If you decide to do so, switch on **Use discovery endpoint** and enter `{VC_AUTHN_PUBLIC_URL}/.well-known/openid-configuration` to proceed.
To input settings manually, or review them:
@@ -25,11 +25,11 @@ To input settings manually, or review them:
- **Disable User Info**: it is recommended to disable the user info endpoint, since VC Authn does not store/provide user information.
-- **Client ID/Client Secret**: these settings will be used to identify and secure the IdP integration between Keycloak and VC Authn. Make sure the **client secret** parameter is unique to your VC Authn instance. VC-AuthN supports two methods of client authentication: `Client secret sent as basic auth` and `Client secret sent as post`.
+- **Client ID/Client Secret**: these settings will be used to identify and secure the IdP integration between Keycloak and VC Authn. Make sure the **client secret** parameter is unique to your VC Authn instance. ACAPy VC-AuthN supports two methods of client authentication: `Client secret sent as basic auth` and `Client secret sent as post`.
- **Default Scopes**: this must be set to `vc_authn` to instruct the AIM broker which scopes to request from the IdP.
-- **Validate Signatures**: if you want to have the signature of VC-AuthN validated by Keycloak, turn this on, flip the `Use JWKS URL` to true and set `JWKS URL` to `{PUBLIC_VC_AUTHN_URL}/.well-known/openid-configuration/jwks`.
+- **Validate Signatures**: if you want to have the signature of ACAPy VC-AuthN validated by Keycloak, turn this on, flip the `Use JWKS URL` to true and set `JWKS URL` to `{PUBLIC_VC_AUTHN_URL}/.well-known/openid-configuration/jwks`.
- **Forwarded Query Parameters**: set this to `pres_req_conf_id`. This parameter is used by VC Authn to lookup in its database the configuration to generate presentation request to be displayed to the user and the AIM system needs to forward it when initiating the authentication.
@@ -39,7 +39,7 @@ Save the settings and take note of the generated **Redirect URI** and **Client I
### Configuring VC Authn
-VC-AuthN can be configured by using the API endpoints exposed on Swagger at `VC_AUTHN_PUBLIC_URL}/docs`. The `oidc_clients` namespace provides RESTful APIs to create/delete/update clients.
+ACAPy VC-AuthN can be configured by using the API endpoints exposed on Swagger at `VC_AUTHN_PUBLIC_URL}/docs`. The `oidc_clients` namespace provides RESTful APIs to create/delete/update clients.
To register a new client, `POST` a request to the `/clients` endpoint with a payload containing the client id/secret and redirect URL noted at the previous step. Example:
@@ -68,17 +68,17 @@ The following is an example mapper configuration:
## Direct Configuration
-VC-AuthN 2.0 only supports confidential clients, and cannot be configured to be invoked directly from Single-Page applications. For back-end systems, however, the above instructions should still apply.
+ACAPy VC-AuthN 2.0 only supports confidential clients, and cannot be configured to be invoked directly from Single-Page applications. For back-end systems, however, the above instructions should still apply.
## Environment Variables
-Several functions in VC-AuthN can be tweaked by using the following environment variables.
+Several functions in ACAPy VC-AuthN can be tweaked by using the following environment variables.
| Variable | Type | What it does | NOTES |
| ------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| SET_NON_REVOKED | bool | if True, the `non_revoked` attributed will be added to each of the present-proof request `requested_attribute` and `requested_predicate` with 'from=0' and'to=`int(time.time())` | |
-| USE_OOB_PRESENT_PROOF | bool | if True, the present-proof request will be provided as a an [out of band](https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband) invitation with a [present-proof](https://github.com/hyperledger/aries-rfcs/tree/main/features/0037-present-proof) request inside. If False, the present-proof request will be use the [service-decorator](https://github.com/hyperledger/aries-rfcs/tree/main/features/0056-service-decorator) | **TRUE:** BC Wallet supports our OOB Message with a minor glitch, BiFold, Lissi, Trinsic, and Estatus all read the QR code as 'Invalid' |
-| USE_OOB_LOCAL_DID_SERVICE | bool | Instructs VC-AuthN to use a local DID, it must be used when the agent service is not registered on the ledger with a public DID | Use this when `ACAPY_WALLET_LOCAL_DID` is set to `true` in the agent. |
+| USE_OOB_PRESENT_PROOF | bool | if True, the present-proof request will be provided as a an [out of band](https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband) invitation with a [present-proof](https://github.com/hyperledger/aries-rfcs/tree/main/features/0037-present-proof) request inside. If False, the present-proof request will be use the [service-decorator](https://github.com/hyperledger/aries-rfcs/tree/main/features/0056-service-decorator) | **TRUE:** BC Wallet supports our OOB Message, BiFold, Lissi, Trinsic, and Estatus all read the QR code as 'Invalid' |
+| USE_OOB_LOCAL_DID_SERVICE | bool | Instructs ACAPy VC-AuthN to use a local DID, it must be used when the agent service is not registered on the ledger with a public DID | Use this when `ACAPY_WALLET_LOCAL_DID` is set to `true` in the agent. |
| USE_URL_DEEP_LINK | bool | If True, in Mobile mode the BC Wallet deep link will use an encoded URL (`WALLET_DEEP_LINK_PREFIX?_url={redirect URL}`), otherwise will use the encoded connection invitation (`{WALLET_DEEP_LINK_PREFIX}?c_i={connection invitation payload}`) | Default False/.. To control using the `?_url` handler |
| WALLET_DEEP_LINK_PREFIX | string | Custom URI scheme and host to use for deep links (e.g. `{WALLET_DEEP_LINK_PREFIX}?c_i={connection invitation payload`) | Default bcwallet://aries_proof-request |
| LOG_WITH_JSON | bool | If True, logging output should printed as JSON if False it will be pretty printed. | Default behavior will print as JSON. |
@@ -89,16 +89,16 @@ Several functions in VC-AuthN can be tweaked by using the following environment
The basic structure of a proof-request configuration is described [here](README.md#data-model). Additional options are described via the Swagger document, and listed below:
-- `include_v1_attributes`: defaults to `false`, switch to `true` if root-level claims as presented in VC-AuthN v1 are still required for the proof-request.
+- `include_v1_attributes`: defaults to `false`, switch to `true` if root-level claims as presented in ACAPy VC-AuthN v1 are still required for the proof-request.
### Proof Substitution Variables
-Proof Request configurations (as described [here](README.md#data-model)) are pre-set records stored in the VC-AuthN database comprising of the details to make the proof request from.
+Proof Request configurations (as described [here](README.md#data-model)) are pre-set records stored in the ACAPy VC-AuthN database comprising of the details to make the proof request from.
At runtime when the user is directed to the proof challenge, the appropriate configuration is fetched and the proof request built from that.
In certain use cases you may want the proof request to have a specific value in the proof (probably in a requested predicate) generated at that moment rather than preset.
An example could be using today's date, a "right now" timestamp, or an age-check (IE today's date minus 19 years).
-To accomodate this, VC-AuthN **proof substitution variables** can be used as placeholders in the configurations. They can just be added as string in the configuration with a `$` prefix.
+To accomodate this, ACAPy VC-AuthN **proof substitution variables** can be used as placeholders in the configurations. They can just be added as string in the configuration with a `$` prefix.
There are a handful of built-in options:
| Substitution Variable | Details |
@@ -157,7 +157,7 @@ variable_substitution_map.add_variable_substitution(r"\$today_plus_(\d+)_times_(
For an example of this python file see `docker/oidc-controller/config/user_variable_substitution_example.py`
All that is necessary is the adding of substitution variables.These
-changes will be applied by vc-authn during startup. The variable
+changes will be applied by ACAPy VC-AuthN during startup. The variable
`variable_substitution_map` **will already be defined**.
After loading the python file during the service startup each new user
diff --git a/docs/MigrationGuide.md b/docs/MigrationGuide.md
index c68ad1e7..d7c2f414 100644
--- a/docs/MigrationGuide.md
+++ b/docs/MigrationGuide.md
@@ -1,10 +1,10 @@
-# VC-AuthN Migration Guide
+# ACAPy VC-AuthN Migration Guide
-This document contains instructions and tips useful when upgrading VC-AuthN.
+This document contains instructions and tips useful when upgrading ACAPy VC-AuthN.
## 1.x -> 2.x
-The functionality has mostly remained unchanged, however there are some details that need to be acocunted for.
+The functionality has mostly remained unchanged, however there are some details that need to be accounted for.
* Endpoints: `authorization` and `token` endpoints have changed, review the new values by navigating to the `.well-known` URL and update your integration accordingly.
@@ -12,4 +12,4 @@ The functionality has mostly remained unchanged, however there are some details
- The `name` identifier for disclosed attributes has been deprecated, use the `names` array instead.
- If backwards-compatibility with `v1.0` tokens is required, the `include_v1_attributes` flag should be switched to `true` (see the [configuration guide](./ConfigurationGuide.md)).
-* Client Types: VC-AuthN 2.0 currently only supports confidential clients using client id/secret. If public clients were previously registered, they will now need to use an AIM (e.g.: keycloak) as broker.
+* Client Types: ACAPy VC-AuthN 2.0 currently only supports confidential clients using client id/secret. If public clients were previously registered, they will now need to use an AIM (e.g.: keycloak) as broker.
diff --git a/docs/README.md b/docs/README.md
index ce700a7d..730c5f22 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -20,7 +20,7 @@ The integration this document defines is how holders of verifiable credentials c
Like any new technology there is adoption required of new concepts, this particular integration aims to provide an easy integration path that allows parties to start leveraging the power of verifiable credentials for user authentication in a non-disruptive fashion. This is achieved by extending the vastly popular [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) family of specifications.
-In reference to the above diagram. A supporting OP will act as the verifier on behalf of a RP for a verifiable credentials presentation. This mode of integration means RP's that already support OIDC only have to extend their support to making VC-AuthN based OIDC requests to a supported OP, rather than adding full support for verifiable credential interactions directly. The holder will use an IdentityWallet (IW) mobile app to store their verifiable credentials and manage presentation requests from verifiers.
+In reference to the above diagram. A supporting OP will act as the verifier on behalf of a RP for a verifiable credentials presentation. This mode of integration means RP's that already support OIDC only have to extend their support to making ACAPy VC-AuthN based OIDC requests to a supported OP, rather than adding full support for verifiable credential interactions directly. The holder will use an IdentityWallet (IW) mobile app to store their verifiable credentials and manage presentation requests from verifiers.
## Abbreviations
diff --git a/oidc-controller/api/core/aries/__init__.py b/oidc-controller/api/core/acapy/__init__.py
similarity index 100%
rename from oidc-controller/api/core/aries/__init__.py
rename to oidc-controller/api/core/acapy/__init__.py
diff --git a/oidc-controller/api/core/acapy/models.py b/oidc-controller/api/core/acapy/models.py
index b285477f..700311cb 100644
--- a/oidc-controller/api/core/acapy/models.py
+++ b/oidc-controller/api/core/acapy/models.py
@@ -1,4 +1,4 @@
-from ..aries import OutOfBandMessage
+from . import OutOfBandMessage
from pydantic import BaseModel
diff --git a/oidc-controller/api/core/aries/out_of_band.py b/oidc-controller/api/core/acapy/out_of_band.py
similarity index 92%
rename from oidc-controller/api/core/aries/out_of_band.py
rename to oidc-controller/api/core/acapy/out_of_band.py
index af805154..b6785320 100644
--- a/oidc-controller/api/core/aries/out_of_band.py
+++ b/oidc-controller/api/core/acapy/out_of_band.py
@@ -19,7 +19,7 @@ class OutOfBandMessage(BaseModel):
)
goal_code: str = Field(default="request-proof")
label: str = Field(
- default="vc-authn Out-of-Band present-proof authorization request"
+ default="acapy-vc-authn Out-of-Band present-proof authorization request"
)
request_attachments: list[OutOfBandPresentProofAttachment] = Field(
alias="requests~attach"
diff --git a/oidc-controller/api/core/aries/present_proof_attachment.py b/oidc-controller/api/core/acapy/present_proof_attachment.py
similarity index 100%
rename from oidc-controller/api/core/aries/present_proof_attachment.py
rename to oidc-controller/api/core/acapy/present_proof_attachment.py
diff --git a/oidc-controller/api/core/aries/present_proof_presentation.py b/oidc-controller/api/core/acapy/present_proof_presentation.py
similarity index 93%
rename from oidc-controller/api/core/aries/present_proof_presentation.py
rename to oidc-controller/api/core/acapy/present_proof_presentation.py
index dd373353..879da158 100644
--- a/oidc-controller/api/core/aries/present_proof_presentation.py
+++ b/oidc-controller/api/core/acapy/present_proof_presentation.py
@@ -2,7 +2,7 @@
import base64
from pydantic import BaseModel, ConfigDict, Field
-from api.core.aries import PresentProofv20Attachment, ServiceDecorator
+from api.core.acapy import PresentProofv20Attachment, ServiceDecorator
class PresentationRequestMessage(BaseModel):
diff --git a/oidc-controller/api/core/aries/service_decorator.py b/oidc-controller/api/core/acapy/service_decorator.py
similarity index 89%
rename from oidc-controller/api/core/aries/service_decorator.py
rename to oidc-controller/api/core/acapy/service_decorator.py
index 0df633d9..f6aea580 100644
--- a/oidc-controller/api/core/aries/service_decorator.py
+++ b/oidc-controller/api/core/acapy/service_decorator.py
@@ -15,7 +15,9 @@ class OOBServiceDecorator(ServiceDecorator):
recipient_keys: list[str] | None = Field(default=None, alias="recipientKeys")
routing_keys: list[str] | None = Field(default=None, alias="routingKeys")
service_endpoint: str | None = Field(default=None, alias="serviceEndpoint")
- id: str = Field(default="did:vc-authn-oidc:123456789zyxwvutsr#did-communication")
+ id: str = Field(
+ default="did:acapy-vc-authn-oidc:123456789zyxwvutsr#did-communication"
+ )
type: str = Field(default="did-communication")
priority: int = 0
diff --git a/oidc-controller/api/core/config.py b/oidc-controller/api/core/config.py
index 76f0efd7..5968f2d2 100644
--- a/oidc-controller/api/core/config.py
+++ b/oidc-controller/api/core/config.py
@@ -134,7 +134,9 @@ class EnvironmentEnum(str, Enum):
class GlobalConfig(BaseSettings):
- TITLE: str = os.environ.get("CONTROLLER_APP_TITLE", "vc-authn-oidc Controller")
+ TITLE: str = os.environ.get(
+ "CONTROLLER_APP_TITLE", "acapy-vc-authn-oidc Controller"
+ )
DESCRIPTION: str = os.environ.get(
"CONTROLLER_APP_DESCRIPTION",
"An oidc authentication solution for verification credentials",
diff --git a/oidc-controller/api/core/oidc/tests/__mocks__.py b/oidc-controller/api/core/oidc/tests/__mocks__.py
index 3057c8e0..0c17457e 100644
--- a/oidc-controller/api/core/oidc/tests/__mocks__.py
+++ b/oidc-controller/api/core/oidc/tests/__mocks__.py
@@ -1326,7 +1326,7 @@
auth_session = AuthSession(
pres_exch_id="e444bc3e-346d-47d1-882d-39c014b8978c",
expired_timestamp=datetime.now() + timedelta(seconds=3000),
- ver_config_id="showcase-person",
+ ver_config_id="test-proof",
request_parameters={
"scope": "openid vc_authn",
"state": "oFLNfUyzDtWHmc61dNiQZkVZRsRUUXZ5KZIiQBeQuJQ.xfaKQBh1xfQ.T02DEr3QRTmMUfjegc9fQQ",
@@ -1355,7 +1355,7 @@
),
},
proof_request=VerificationProofRequest(
- name="BCGov Verified Email",
+ name="Verified Email",
version="1.0",
requested_attributes=[
{
diff --git a/oidc-controller/api/routers/oidc.py b/oidc-controller/api/routers/oidc.py
index 165cf78a..2d4d7073 100644
--- a/oidc-controller/api/routers/oidc.py
+++ b/oidc-controller/api/routers/oidc.py
@@ -19,7 +19,7 @@
from ..authSessions.crud import AuthSessionCreate, AuthSessionCRUD
from ..authSessions.models import AuthSessionPatch, AuthSessionState, AuthSession
from ..core.acapy.client import AcapyClient
-from ..core.aries import (
+from ..core.acapy import (
PresentationRequestMessage,
PresentProofv20Attachment,
ServiceDecorator,
diff --git a/oidc-controller/api/templates/assets/img/header-logo.svg b/oidc-controller/api/templates/assets/img/header-logo.svg
index 2774c342..0721e457 100644
--- a/oidc-controller/api/templates/assets/img/header-logo.svg
+++ b/oidc-controller/api/templates/assets/img/header-logo.svg
@@ -1 +1,54 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/oidc-controller/api/templates/ver_config_explorer.html b/oidc-controller/api/templates/ver_config_explorer.html
index fe0f932b..97ea5531 100644
--- a/oidc-controller/api/templates/ver_config_explorer.html
+++ b/oidc-controller/api/templates/ver_config_explorer.html
@@ -48,17 +48,17 @@
- Proof of Concept. For internal use only at this time.
+ Proof of Concept.
@@ -135,42 +135,11 @@
{% endfor %}
-
-
-
-
-
-
Need to add a Presentation Request?
-
- If you are integrating VCAuthN into your line of business
- application and do not see the Presentation Request you need,
- you can request an addition from us.
-