amplify-js: Amplify missing the ability to programmatically create a user session using Cognito (id, access, refresh) tokens
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
# Put output below this line
System:
OS: macOS 10.15.7
CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
Memory: 56.16 MB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 14.17.0 - /usr/local/opt/node@14/bin/node
npm: 6.14.13 - /usr/local/opt/node@14/bin/npm
Browsers:
Chrome: 91.0.4472.164
Firefox: 86.0
Safari: 14.0.3
Safari Technology Preview: 14.2
npmPackages:
@aws-amplify/ui-react: ^1.2.7 => 1.2.7
@babel/core: ^7.14.8 => 7.14.8 (7.12.3)
@babel/plugin-proposal-class-properties: ^7.14.5 => 7.14.5 (7.12.1)
@babel/plugin-proposal-decorators: ^7.14.5 => 7.14.5 (7.12.1)
@babel/plugin-proposal-do-expressions: ^7.14.5 => 7.14.5
@babel/plugin-proposal-export-default-from: ^7.14.5 => 7.14.5
@babel/plugin-proposal-export-namespace-from: ^7.14.5 => 7.14.5
@babel/plugin-proposal-function-sent: ^7.14.5 => 7.14.5
@babel/plugin-proposal-json-strings: ^7.14.5 => 7.14.5
@babel/plugin-proposal-logical-assignment-operators: ^7.14.5 => 7.14.5
@babel/plugin-proposal-nullish-coalescing-operator: ^7.14.5 => 7.14.5 (7.12.1)
@babel/plugin-proposal-numeric-separator: ^7.14.5 => 7.14.5 (7.12.1)
@babel/plugin-proposal-optional-chaining: ^7.14.5 => 7.14.5 (7.12.1)
@babel/plugin-proposal-pipeline-operator: ^7.14.8 => 7.14.8
@babel/plugin-proposal-throw-expressions: ^7.14.5 => 7.14.5
@babel/plugin-syntax-dynamic-import: ^7.8.3 => 7.8.3
@babel/plugin-syntax-import-meta: ^7.10.4 => 7.10.4
@babel/plugin-transform-runtime: ^7.14.5 => 7.14.5 (7.12.1)
@babel/preset-env: ^7.14.8 => 7.14.8 (7.12.1)
@babel/preset-react: ^7.14.5 => 7.14.5 (7.12.1)
@babel/register: ^7.14.5 => 7.14.5
@fortawesome/fontawesome-svg-core: ^1.2.35 => 1.2.35
@fortawesome/free-brands-svg-icons: ^5.15.3 => 5.15.3
@fortawesome/free-regular-svg-icons: ^5.15.3 => 5.15.3
@fortawesome/free-solid-svg-icons: ^5.15.3 => 5.15.3
@fortawesome/pro-light-svg-icons: ^5.15.3 => 5.15.3
@fortawesome/pro-regular-svg-icons: ^5.15.3 => 5.15.3
@fortawesome/pro-solid-svg-icons: ^5.15.3 => 5.15.3
@fortawesome/react-fontawesome: ^0.1.14 => 0.1.14
@testing-library/jest-dom: ^5.14.1 => 5.14.1
@testing-library/react: ^12.0.0 => 12.0.0
@testing-library/user-event: ^13.2.0 => 13.2.0
@vue/preload-webpack-plugin: ^2.0.0 => 2.0.0
amazon-cognito-identity-js: ^5.0.6 => 5.0.6
aws-amplify: ^4.2.1 => 4.2.1
axios: ^0.21.1 => 0.21.1
babel-loader: ^8.2.2 => 8.2.2 (8.1.0)
bootstrap: ^5.0.2 => 5.0.2
bundle-stats-webpack-plugin: ^3.0.1 => 3.0.1
clean-webpack-plugin: ^4.0.0-alpha.0 => 4.0.0-alpha.0
compression-webpack-plugin: ^8.0.1 => 8.0.1
core-js: ^3.15.2 => 3.15.2 (2.6.12, 1.2.7)
css-loader: ^5.2.7 => 5.2.7 (4.3.0)
css-minimizer-webpack-plugin: ^3.0.2 => 3.0.2
eslint: ^7.31.0 => 7.31.0
eslint-config-airbnb: ^18.2.1 => 18.2.1
eslint-loader: ^4.0.2 => 4.0.2
eslint-plugin-import: ^2.23.4 => 2.23.4
eslint-plugin-jsx-a11y: ^6.4.1 => 6.4.1
eslint-plugin-react: ^7.24.0 => 7.24.0
file-loader: ^6.2.0 => 6.2.0 (6.1.1)
google-map-react: ^2.1.10 => 2.1.10
html-webpack-plugin: ^5.3.2 => 5.3.2 (4.5.0)
image-minimizer-webpack-plugin: ^2.2.0 => 2.2.0
imagemin-gifsicle: ^7.0.0 => 7.0.0
imagemin-jpegtran: ^7.0.0 => 7.0.0
imagemin-mozjpeg: ^9.0.0 => 9.0.0
imagemin-optipng: ^8.0.0 => 8.0.0
imagemin-svgo: ^9.0.0 => 9.0.0
lodash-webpack-plugin: ^0.11.6 => 0.11.6
lodash.isequal: ^4.5.0 => 4.5.0
mini-css-extract-plugin: ^1.6.2 => 1.6.2 (0.11.3)
node-sass: ^6.0.1 => 6.0.1
normalizr: ^3.6.1 => 3.6.1
postcss: ^8.3.6 => 8.3.6 (7.0.36)
react: ^17.0.2 => 17.0.2 (16.14.0, 0.14.10)
react-bootstrap: ^1.6.1 => 1.6.1
react-bootstrap/AbstractNav: undefined ()
react-bootstrap/AbstractNavItem: undefined ()
react-bootstrap/Accordion: undefined ()
react-bootstrap/AccordionCollapse: undefined ()
react-bootstrap/AccordionContext: undefined ()
react-bootstrap/AccordionToggle: undefined ()
react-bootstrap/Alert: undefined ()
react-bootstrap/Badge: undefined ()
react-bootstrap/BootstrapModalManager: undefined ()
react-bootstrap/Breadcrumb: undefined ()
react-bootstrap/BreadcrumbItem: undefined ()
react-bootstrap/Button: undefined ()
react-bootstrap/ButtonGroup: undefined ()
react-bootstrap/ButtonToolbar: undefined ()
react-bootstrap/Card: undefined ()
react-bootstrap/CardColumns: undefined ()
react-bootstrap/CardContext: undefined ()
react-bootstrap/CardDeck: undefined ()
react-bootstrap/CardGroup: undefined ()
react-bootstrap/CardImg: undefined ()
react-bootstrap/Carousel: undefined ()
react-bootstrap/CarouselCaption: undefined ()
react-bootstrap/CarouselItem: undefined ()
react-bootstrap/CloseButton: undefined ()
react-bootstrap/Col: undefined ()
react-bootstrap/Collapse: undefined ()
react-bootstrap/Container: undefined ()
react-bootstrap/Dropdown: undefined ()
react-bootstrap/DropdownButton: undefined ()
react-bootstrap/DropdownItem: undefined ()
react-bootstrap/DropdownMenu: undefined ()
react-bootstrap/DropdownToggle: undefined ()
react-bootstrap/ElementChildren: undefined ()
react-bootstrap/Fade: undefined ()
react-bootstrap/Feedback: undefined ()
react-bootstrap/Figure: undefined ()
react-bootstrap/FigureCaption: undefined ()
react-bootstrap/FigureImage: undefined ()
react-bootstrap/Form: undefined ()
react-bootstrap/FormCheck: undefined ()
react-bootstrap/FormCheckInput: undefined ()
react-bootstrap/FormCheckLabel: undefined ()
react-bootstrap/FormContext: undefined ()
react-bootstrap/FormControl: undefined ()
react-bootstrap/FormFile: undefined ()
react-bootstrap/FormFileInput: undefined ()
react-bootstrap/FormFileLabel: undefined ()
react-bootstrap/FormGroup: undefined ()
react-bootstrap/FormLabel: undefined ()
react-bootstrap/FormText: undefined ()
react-bootstrap/Image: undefined ()
react-bootstrap/InputGroup: undefined ()
react-bootstrap/Jumbotron: undefined ()
react-bootstrap/ListGroup: undefined ()
react-bootstrap/ListGroupItem: undefined ()
react-bootstrap/Media: undefined ()
react-bootstrap/Modal: undefined ()
react-bootstrap/ModalBody: undefined ()
react-bootstrap/ModalContext: undefined ()
react-bootstrap/ModalDialog: undefined ()
react-bootstrap/ModalFooter: undefined ()
react-bootstrap/ModalHeader: undefined ()
react-bootstrap/ModalTitle: undefined ()
react-bootstrap/Nav: undefined ()
react-bootstrap/NavContext: undefined ()
react-bootstrap/NavDropdown: undefined ()
react-bootstrap/NavItem: undefined ()
react-bootstrap/NavLink: undefined ()
react-bootstrap/Navbar: undefined ()
react-bootstrap/NavbarBrand: undefined ()
react-bootstrap/NavbarCollapse: undefined ()
react-bootstrap/NavbarContext: undefined ()
react-bootstrap/NavbarToggle: undefined ()
react-bootstrap/Overlay: undefined ()
react-bootstrap/OverlayTrigger: undefined ()
react-bootstrap/PageItem: undefined ()
react-bootstrap/Pagination: undefined ()
react-bootstrap/Popover: undefined ()
react-bootstrap/PopoverContent: undefined ()
react-bootstrap/PopoverTitle: undefined ()
react-bootstrap/ProgressBar: undefined ()
react-bootstrap/ResponsiveEmbed: undefined ()
react-bootstrap/Row: undefined ()
react-bootstrap/SafeAnchor: undefined ()
react-bootstrap/SelectableContext: undefined ()
react-bootstrap/Spinner: undefined ()
react-bootstrap/SplitButton: undefined ()
react-bootstrap/Switch: undefined ()
react-bootstrap/Tab: undefined ()
react-bootstrap/TabContainer: undefined ()
react-bootstrap/TabContent: undefined ()
react-bootstrap/TabContext: undefined ()
react-bootstrap/TabPane: undefined ()
react-bootstrap/Table: undefined ()
react-bootstrap/Tabs: undefined ()
react-bootstrap/ThemeProvider: undefined ()
react-bootstrap/Toast: undefined ()
react-bootstrap/ToastBody: undefined ()
react-bootstrap/ToastContext: undefined ()
react-bootstrap/ToastHeader: undefined ()
react-bootstrap/ToggleButton: undefined ()
react-bootstrap/ToggleButtonGroup: undefined ()
react-bootstrap/Tooltip: undefined ()
react-bootstrap/createChainedFunction: undefined ()
react-bootstrap/createWithBsPrefix: undefined ()
react-bootstrap/divWithClassName: undefined ()
react-bootstrap/helpers: undefined ()
react-bootstrap/transitionEndListener: undefined ()
react-bootstrap/triggerBrowserReflow: undefined ()
react-bootstrap/types: undefined ()
react-bootstrap/usePopperMarginModifiers: undefined ()
react-bootstrap/useWrappedRefWithWarning: undefined ()
react-datepicker: ^4.1.1 => 4.1.1
react-dom: ^17.0.2 => 17.0.2 (16.14.0, 0.14.10)
react-ga: ^3.3.0 => 3.3.0
react-image-lightbox: ^5.1.4 => 5.1.4
react-redux: ^7.2.4 => 7.2.4
react-router-dom: ^5.2.0 => 5.2.0
react-router-hash-link: ^2.4.3 => 2.4.3
react-scripts: 4.0.3 => 4.0.3
react-star-rating-component: ^1.4.1 => 1.4.1
react-tooltip: ^4.2.21 => 4.2.21
redux: ^4.1.0 => 4.1.0
redux-actions: ^2.6.5 => 2.6.5
redux-devtools: ^3.7.0 => 3.7.0
redux-devtools-extension: ^2.13.9 => 2.13.9
redux-promise-middleware: ^6.1.2 => 6.1.2
redux-promise-middleware-actions: ^3.1.0 => 3.1.0
redux-thunk: ^2.3.0 => 2.3.0
remote-redux-devtools: ^0.5.16 => 0.5.16
sass-loader: ^12.1.0 => 12.1.0 (10.2.0)
script-ext-html-webpack-plugin: ^2.1.5 => 2.1.5
source-sans-pro: ^3.6.0 => 3.6.0
style-loader: ^3.2.1 => 3.2.1 (1.3.0)
svgo: ^2.3.1 => 2.3.1 (1.3.2)
terser-webpack-plugin: ^5.1.4 => 5.1.4 (4.2.3, 1.4.5)
url-loader: ^4.1.1 => 4.1.1
uuid: ^8.3.2 => 8.3.2 (3.4.0, 3.3.2, 7.0.3, 3.2.1)
webpack: ^5.46.0 => 5.46.0 (4.44.2)
webpack-bundle-analyzer: ^4.4.2 => 4.4.2
webpack-cli: ^4.7.2 => 4.7.2
webpack-dev-server: ^3.11.2 => 3.11.2 (3.11.1)
webpack-merge: ^5.8.0 => 5.8.0
webpack-visualizer-plugin: ^0.1.11 => 0.1.11
npmGlobalPackages:
@aws-amplify/cli: 0.1.41
babel-upgrade: 0.0.23
cordova-check-plugins: 4.0.5
cordova: 9.0.0
eslint-config-standard-react: 11.0.1
eslint-config-standard: 16.0.2
eslint: 7.29.0
ios-deploy: 1.10.0
less: 3.9.0
npm-check-updates: 11.7.1
npm: 7.13.0
phonegap: 8.0.0
svgo: 2.3.0
uglify-js: 3.6.0
webpack-cli: 3.3.12
webpack-dev-server: 3.11.2
webpack: 5.37.1
Describe the bug
I’m working on a straight react js mobile application using cordova, and want to use Amplify with Social Sign On. I can’t reliably use deep links, and need to handle the authentication flow within the app itself. I’m able to get to the point where I receive the authorization code grant URL from Cognito. But there doesn’t appear to be a way in Amplify to create the user session using the tokens provided by Cognito.
This functionality seems to have once existed in amazon-cognito-auth-js with the parseCognitoWebResponse() method. However, there is only one reference to CognitoAuth client in Auth.ts on line 209. It does not seem that you can retrieve a CognitoAuth client from the Auth object. So it would seem this capability is no longer supported anymore.
Amplify’s Auth._oAuthHandler.handleAuthResponse() function does parse a Cognito authorization code grant url against the oauth2/token endpoint, and returns the idtoken, refreshtoken and accesstoken, but the handleAuthResponse function does not store these tokens or create a Cognito User Session. There does not appear to be any way to create a User Session, using these tokens, via Amplify, the amazon-cognito-identity-js library, or the AWS JS SDK v3 (Cognito Identity Provider).
This issue was acknowledged by the Amplify team in a comment by @powerful23 in #825 — there should be a way to create a session apart from having to use the urlListener, and worst case, provide tokens to Amplify to create a user session. The Amplify team coded a rudimentary capability, but it was never released out of beta. #825 seems to have been closed without any resolution.
Based on comments in #825, it may be possible to trick Amplify by pushing these tokens into storage, but that’s super hacky.
Am I missing something?
Expected behavior
I would expect the Amplify Authorization library to offer some mechanism to both (1) parse the authorization code grant response from Cognito, and (2) provide a way of creating a user session with the provided tokens without the reliance on urlListener. Just having the first by itself is not helpful. The lack of being able to create a user session greatly constrains Amplify’s usefulness as soon as you go offroad.
Reproduction steps
Try to create a Cognito user session without urlListener, or using Auth._oAuthHandler.handleAuthResponse(). It doesn’t appear to be possible.
Code Snippet
// Put your code below this line.
Log output
// Put your logs below this line
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 2
- Comments: 18
Continuing to work with this --it seems like you can get Amplify to pick up the session if you cache it in localstorage as described in #825 (very convoluted). Been working all morning to find a cleaner way to do this using either Amplify or the amazon-cognito-identity-js package; the best I’ve come up with so far (which relies on the code in my last post) is this:
Now, Amplify will return the authenticated user correctly. Is there a cleaner/simpler way of doing this? If Amplify/Auth are already configured, and you have the CognitoUserSession separately, it seems as though there should be a single method that just does the above for you – rather than making the developer have to spend hours upon hours figuring all this out.
I documented my approach in a medium blog. https://medium.com/codex/how-to-process-an-aws-cognito-authorization-code-grant-using-aws-amplify-b49d9ee052ca
Not 100% sure why you’re getting ‘undefined’; I know typescript takes issue with the fact that _oAuthHandler is private. There are ways to bypass this I’ve read and access the method, but it’s not recommended. I submitted a feature request to make this method public (linked earlier in this issue).
Thank you very much @jglesner for your implementation it saved me a lot of time. I updated the code to a TypeScript function for my purpose. Maybe someone will find it useful:
@chanpod There’s a separate feature request for this: https://github.com/aws-amplify/amplify-js/issues/8933. You might +1 it to support the request.
Based on the error, my first guess would be that Amplify/Auth is misconfigured. Otherwise, Auth._oAuthHandler wouldn’t be undefined. I looked at your post #9917, and I don’t see that you’ve provided your oauth config to Amplify.configure({ … }). I’ve pasted the oauth segment below; you can see how this snippet fits in the overall Amplify config as shown in the documentation. Can you confirm whether you’ve configured Cognito >> User Pools >> App Integration, and included that information w/ your configuration?
You can
console.log(Amplify);to see whether AmplifyClass > Auth > _oAuthHandler is configured. If you don’t see the info above filled in, then that’s why _oAuthHandler is undefined.You seem to have solved your use case. Our team will consider your feature request in the future for Auth