-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Improve user authentication handling #547
Changes from all commits
abc0411
9d9a96a
4c02c37
7d30b90
8e1ca57
46286a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -126,43 +126,38 @@ your IBM Q Experience account: | |
|
||
#### Configure your API token and QX credentials | ||
|
||
|
||
1. Create an _[IBM Q Experience](https://quantumexperience.ng.bluemix.net) > Account_ if you haven't already done so. | ||
|
||
2. Get an API token from the IBM Q Experience website under _My Account > Advanced > API Token_. This API token allows you to execute your programs with the IBM Q Experience backends. See: [Example](doc/example_real_backend.rst). | ||
3. We are going to create a new file called `Qconfig.py` and insert the API token into it. This file must have these contents: | ||
|
||
```python | ||
APItoken = 'MY_API_TOKEN' | ||
3. We are now going to add the necessary credentials to QISKit. Take your token | ||
from step 2, here called `MY_API_TOKEN`, and pass it to the | ||
`store_credentials` function: | ||
|
||
config = { | ||
'url': 'https://quantumexperience.ng.bluemix.net/api', | ||
# The following should only be needed for IBM Q Network users. | ||
'hub': 'MY_HUB', | ||
'group': 'MY_GROUP', | ||
'project': 'MY_PROJECT' | ||
} | ||
``` | ||
```python | ||
from qiskit import store_credentials | ||
|
||
4. Substitute `MY_API_TOKEN` with your real API Token extracted in step 2. | ||
store_credentials('MY_API_TOKEN') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we say "you don't need to do this more than once"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I would expect that the reader knows that the steps in this whole section "Configure you API token" is to be done once (create account, create token, set it up, etc). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I saw this explained later, it is fine. |
||
``` | ||
|
||
5. If you have access to the IBM Q Network features, you also need to setup the | ||
values for your hub, group, and project. You can do so by filling the | ||
`config` variable with the values you can find on your IBM Q account | ||
page. | ||
4. If you have access to the IBM Q Network features, you also need to pass the | ||
values for your url, hub, group, and project found on your IBM Q account | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be convenient to link There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same text that was there before, and is only of interest to hub members. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking although It is never late for clarifying the docs. |
||
page to `store_credentials`. | ||
|
||
Once the `Qconfig.py` file is set up, you have to move it under the same directory/folder where your program/tutorial resides, so it can be imported and be used to authenticate with the `register()` function. For example: | ||
After calling `store_credentials()`, your credentials will be stored into disk. | ||
Once they are stored, Qiskit will automatically load and use them in your program | ||
via: | ||
|
||
```python | ||
from qiskit import register | ||
import Qconfig | ||
|
||
register(Qconfig.APItoken, Qconfig.config["url"], | ||
hub=Qconfig.config["hub"], | ||
group=Qconfig.config["group"], | ||
project=Qconfig.config["project"]) | ||
register() | ||
``` | ||
|
||
For more details on this and more information see | ||
For more details on installing Qiskit and for alternative methods for passing | ||
the IBM QX credentials, such as using environment variables, sending them | ||
explicitly and support for the `Qconfig.py` method available in previous | ||
versions, please check | ||
[our Qiskit documentation](https://www.qiskit.org/documentation/). | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,19 +41,113 @@ This will install the latest stable release along with all the dependencies. | |
you haven't already done so | ||
- Get an API token from the IBM Q experience website under “My | ||
Account” > “Personal Access Token” | ||
- The API token needs to be placed in a file called ``Qconfig.py``. For | ||
convenience, we provide a default version of this file that you | ||
can use as a reference: `Qconfig.py.default`_. After downloading that | ||
file, copy it into the folder where you will be invoking the SDK (on | ||
Windows, replace ``cp`` with ``copy``): | ||
|
||
.. code:: sh | ||
|
||
cp Qconfig.py.default Qconfig.py | ||
3.1 Automatically loading credentials | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Since Qiskit 0.6, an automatic method that looks for the credentials in several | ||
places can be used for streamlining the setting up of the IBM Q authentication. | ||
This implies that you can set or store your API credentials once after | ||
installation, and when you want to use them, you can simply run: | ||
|
||
.. code:: python | ||
|
||
from qiskit import register | ||
|
||
register() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documenting the new way of registering by providing three sections with exactly the same example can be misleading. The user can think there is an error in the example or something magic is happening behind the scenes. My recommendation is to introduce There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. |
||
|
||
This ``register()`` call (without parameters) performs the automatic loading | ||
of the credentials from several sources, and authenticates against IBM Q, | ||
making the online devices available to your program. Please use one of the | ||
following methods for storing the credentials before calling the automatic | ||
registration: | ||
|
||
3.1.1 Store API credentials locally | ||
""""""""""""""""""""""""""""""""""" | ||
|
||
For most users, storing your API credentials is the most convenient approach. | ||
Your information is stored locally in a configuration file called `qiskitrc`, | ||
and once stored, you can use the credentials without explicitly passing them | ||
to your program. | ||
|
||
To store your information, simply run: | ||
|
||
.. code:: python | ||
|
||
from qiskit import store_credentials | ||
|
||
store_credentials('MY_API_TOKEN') | ||
|
||
|
||
where `MY_API_TOKEN` should be replaced with your token. | ||
|
||
If you are on the IBM Q network, you must also pass `url`, | ||
`hub`, `group`, and `project` arguments to `store_credentials`: | ||
|
||
|
||
.. code:: python | ||
|
||
from qiskit import store_credentials | ||
|
||
store_credentials('MY_API_TOKEN', url='http://...', hub='HUB', | ||
group='GROUP', project='PROJECT') | ||
|
||
3.1.2 Load API credentials from environment variables | ||
""""""""""""""""""""""""""""""""""""""""""""""""""""" | ||
|
||
- Open your ``Qconfig.py``, remove the ``#`` from the beginning of the API | ||
token line, and copy/paste your API token into the space between the | ||
quotation marks on that line. Save and close the file. | ||
For more advanced users, it is possible to load API credentials from | ||
environment variables. Specifically, you can set the following environment | ||
variables: | ||
|
||
* `QE_TOKEN`, | ||
* `QE_URL` | ||
* `QE_HUB` | ||
* `QE_GROUP` | ||
* `QE_PROJECT`. | ||
|
||
Note that if they are present in your environment, they will take precedence | ||
over the credentials stored in disk. | ||
|
||
3.1.3 Load API credentials from Qconfig.py | ||
"""""""""""""""""""""""""""""""""""""""""" | ||
|
||
For compatibility with configurations set for Qiskit versions earlier than 0.6, | ||
the credentials can also be stored in a file called ``Qconfig.py`` placed in | ||
the directory where your program is invoked from. For convenience, we provide | ||
a default version of this file you can use as a reference - using your favorite | ||
editor, create a ``Qconfig.py`` file in the folder of your program with the | ||
following contents: | ||
|
||
.. code:: python | ||
|
||
APItoken = 'PUT_YOUR_API_TOKEN_HERE' | ||
|
||
config = { | ||
'url': 'https://quantumexperience.ng.bluemix.net/api', | ||
|
||
# If you have access to IBM Q features, you also need to fill the "hub", | ||
# "group", and "project" details. Replace "None" on the lines below | ||
# with your details from Quantum Experience, quoting the strings, for | ||
# example: 'hub': 'my_hub' | ||
# You will also need to update the 'url' above, pointing it to your custom | ||
# URL for IBM Q. | ||
'hub': None, | ||
'group': None, | ||
'project': None | ||
} | ||
|
||
if 'APItoken' not in locals(): | ||
raise Exception('Please set up your access token. See Qconfig.py.') | ||
|
||
And customize the following lines: | ||
|
||
* copy/paste your API token into the space between the quotation marks on the | ||
first line (``APItoken = 'PUT_YOUR_API_TOKEN_HERE'``). | ||
* if you have access to the IBM Q features, you also need to setup the | ||
values for your url, hub, group, and project. You can do so by filling the | ||
``config`` variable with the values you can find on your IBM Q account | ||
page. | ||
|
||
For example, a valid and fully configured ``Qconfig.py`` file would look like: | ||
|
||
|
@@ -65,13 +159,8 @@ For example, a valid and fully configured ``Qconfig.py`` file would look like: | |
'url': 'https://quantumexperience.ng.bluemix.net/api' | ||
} | ||
|
||
- If you have access to the IBM Q features, you also need to setup the | ||
values for your hub, group, and project. You can do so by filling the | ||
``config`` variable with the values you can find on your IBM Q account | ||
page. | ||
|
||
For example, a valid and fully configured ``Qconfig.py`` file for IBM Q | ||
users would look like: | ||
For IBM Q users, a valid and fully configured ``Qconfig.py`` file would look | ||
like: | ||
|
||
.. code:: python | ||
|
||
|
@@ -85,6 +174,26 @@ users would look like: | |
'project': 'MY_PROJECT' | ||
} | ||
|
||
Note that if a ``Qconfig.py`` file is present in your directory, it will take | ||
precedence over the environment variables or the credentials stored in disk. | ||
|
||
3.2 Manually loading credentials | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
In more complex scenarios or for users that need finer control over multiple | ||
accounts, please note that you can pass the API token and the other parameters | ||
directly to the ``register()`` function, which will ignore the automatic | ||
loading of the credentials and use the arguments directly. For example:: | ||
|
||
.. code:: python | ||
|
||
from qiskit import register | ||
|
||
register('MY_API_TOKEN', url='https://my.url') | ||
|
||
will try to authenticate using ``MY_API_TOKEN`` and the specified URL, | ||
regardless of the configuration stored in the config file, the environment | ||
variables, or the ``Qconfig.py`` file, if any. | ||
|
||
Install Jupyter-based tutorials | ||
=============================== | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,11 @@ | |
|
||
"""Helper module for simplified QISKit usage.""" | ||
|
||
import logging | ||
import warnings | ||
from qiskit import transpiler, QISKitError | ||
from qiskit.backends.ibmq import IBMQProvider | ||
from qiskit.wrapper import credentials | ||
from qiskit.wrapper.defaultqiskitprovider import DefaultQISKitProvider | ||
from ._circuittoolkit import circuit_from_qasm_file, circuit_from_qasm_string | ||
|
||
|
@@ -19,11 +21,22 @@ | |
_DEFAULT_PROVIDER = DefaultQISKitProvider() | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def register(*args, provider_class=IBMQProvider, **kwargs): | ||
""" | ||
Authenticate against an online backend provider. | ||
This is a factory method that returns the provider that gets registered. | ||
|
||
Note that if no parameters are passed, this method will try to | ||
automatically discover the credentials for IBMQ in the following places, | ||
in order:: | ||
|
||
1. in the `Qconfig.py` file in the current working directory. | ||
2. in the environment variables. | ||
3. in the `qiskitrc` configuration file. | ||
|
||
Args: | ||
args (tuple): positional arguments passed to provider class initialization | ||
provider_class (BaseProvider): provider class | ||
|
@@ -45,9 +58,18 @@ def register(*args, provider_class=IBMQProvider, **kwargs): | |
BaseProvider: the provider instance that was just registered. | ||
|
||
Raises: | ||
QISKitError: if the provider could not be registered | ||
(e.g. due to conflict) | ||
QISKitError: if the provider could not be registered (e.g. due to | ||
conflict, or if no credentials were provided.) | ||
""" | ||
# Try to autodiscover credentials if not passed. | ||
if not args and not kwargs and provider_class == IBMQProvider: | ||
kwargs = credentials.discover_credentials().get( | ||
credentials.get_account_name(IBMQProvider)) or {} | ||
if not kwargs: | ||
raise QISKitError( | ||
'No IBMQ credentials found. Please pass them explicitly or ' | ||
'store them before calling register() with store_credentials()') | ||
|
||
try: | ||
provider = provider_class(*args, **kwargs) | ||
except Exception as ex: | ||
|
@@ -79,8 +101,36 @@ def registered_providers(): | |
return list(_DEFAULT_PROVIDER.providers) | ||
|
||
|
||
# Functions for inspecting and retrieving backends. | ||
def store_credentials(token, url='https://quantumexperience.ng.bluemix.net/api', | ||
hub=None, group=None, project=None, proxies=None, | ||
verify=True, overwrite=False): | ||
""" | ||
Store credentials for the IBMQ account in the config file. | ||
|
||
Args: | ||
token (str): The token used to register on the online backend such | ||
as the quantum experience. | ||
url (str): The url used for online backend such as the quantum | ||
experience. | ||
hub (str): The hub used for online backend. | ||
group (str): The group used for online backend. | ||
project (str): The project used for online backend. | ||
proxies (dict): Proxy configuration for the API, as a dict with | ||
'urls' and credential keys. | ||
verify (bool): If False, ignores SSL certificates errors. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, this is just the old text. |
||
overwrite (bool): overwrite existing credentials. | ||
|
||
Raises: | ||
QISKitError: if the credentials already exist and overwrite==False. | ||
""" | ||
credentials.store_credentials( | ||
provider_class=IBMQProvider, overwrite=overwrite, | ||
token=token, url=url, hub=hub, group=group, project=project, | ||
proxies=proxies, verify=verify | ||
) | ||
|
||
|
||
# Functions for inspecting and retrieving backends. | ||
|
||
def available_backends(filters=None, compact=True): | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-blocking: it seems we are using soft wrapping so there is no need of manually breaking the lines. I think we should be consistent here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we are not really using soft-wrapping in most of the
README.md
- and technically using line wrapping is more in line with the rest of the file (if I recall correctly, we did have full hard-wrapping for the file at one point in time, but lots of changes were made that resulted in the current mix). I'd love indeed to have it fully consistent one way or the other eventually, but seems out of the scope of this PR.