Skip to content
This repository has been archived by the owner on Sep 29, 2023. It is now read-only.

Link to wiki from Readme. #152

Merged
merged 14 commits into from
Jun 4, 2018
Merged
94 changes: 17 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,33 @@
# Microsoft Azure Active Directory Authentication Library (ADAL) for Python

The ADAL for python library makes it easy for python applications to authenticate to AAD in order to access AAD protected web resources.
`master` branch | `dev` branch | Reference Docs
--------------------|-----------------|---------------
[![Build Status](https://travis-ci.org/AzureAD/azure-activedirectory-library-for-python.svg?branch=master)](https://travis-ci.org/AzureAD/azure-activedirectory-library-for-python) | [![Build Status](https://travis-ci.org/AzureAD/azure-activedirectory-library-for-python.svg?branch=dev)](https://travis-ci.org/AzureAD/azure-activedirectory-library-for-python) | [![Documentation Status](https://readthedocs.org/projects/adal-python/badge/?version=latest)](https://adal-python.readthedocs.io/en/latest/?badge=latest)

## Usage
|[Getting Started](https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki)| [Docs](https://aka.ms/aaddev)| [Samples](https://github.com/azure-samples?query=active-directory)| [Support](README.md#community-help-and-support)
| --- | --- | --- | --- |

### Install
Copy link
Collaborator

@rayluo rayluo May 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the motivation of "Remove duplication. Move content into wiki."
But do we consider keeping some most-seeking contents, such as "how to install", here in this de-facto project home page? In fact, we fine tuned those installation instructions a couple times before, based on real-world supporting request. Better not lose those valuable knowledge and efforts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not losing the instructions recorded over time. They are just in the Wiki page now. I will link to it from the Readme here since it is a "most-seeked" content.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see. Last time I checked, I tried find-by-eye and also "CTRL+F" (i.e. find in page) but could not find keyword "install" in our Wiki home page, its sidebar, or the FAQ page. I was not aware that "install" is inside the "Basic".

Now you have kept this "most-seeked" content by a link to that very wiki page. That is a reasonable solution! 👍


To support 'service principal' with certificate, ADAL depends on the 'cryptography' package. For smooth installation, some suggestions:
The ADAL for Python library enables python applications to authenticate with Azure AD and get tokens to access Azure AD protected web resources.

* For Windows and macOS
You can learn in detail about ADAL Python functionality and usage documented in the [Wiki](https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki).

Upgrade to the latest pip (8.1.2 as of June 2016) and just do `pip install adal`.
## Installation and Usage

* For Linux
You can find the steps to install and basic usage of the library under [ADAL Basics](https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/ADAL-basics) page in the Wiki.

Upgrade to the latest pip (8.1.2 as of June 2016).

You'll need a C compiler, libffi + its development headers, and openssl + its development headers.
Refer to [cryptography installation](https://cryptography.io/en/latest/installation/)

* To install from source:

Upgrade to the latest pip (8.1.2 as of June 2016).
To avoid dealing with compilation errors from cryptography, first run `pip install cryptography` to use statically-linked wheels.
Next, run `python setup.py install`

If you still like to build from source, refer to [cryptography installation](https://cryptography.io/en/latest/installation/).
For more context, start with this [stackoverflow thread](http://stackoverflow.com/questions/22073516/failed-to-install-python-cryptography-package-with-pip-and-setup-py).

### Acquire Token with Client Credentials
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we do have and mention the "sample applications on GitHub" later in this README, but those samples locating in a separated repo may or may not cover all the scenarios ADAL Python supports (as of today, they don't). It would seem still beneficial to keep this minimal "out-of-box" samples sections here. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This content was moved to this Wiki page which links to relavant dev sample for each flow. I will link to this page from Readme.

Copy link
Collaborator

@rayluo rayluo May 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Historically we had a set of real code snippet right here in the README, later we changed it into the current form as a link to those real samples, after we were called out that they became out-of-sync. See full details here.

Now, moving these content to wiki page by actually duplicating those code snippets there, would bring us back to the potential 2-copies-would-become-out-of-sync situation. In fact, as a real-world example, one of our current wiki page technically already outdated, it includes an api_version=None which is no longer needed since our latest 1.0.0 release.

So my suggestion is, because anything that can go wrong will go wrong, so a better approach is to not create duplicate which we would forget to update later.

UPDATE:

  • We now updated the wiki page to contain only links back to the real code in current repo.
  • We could keep the same set of links here in README here (because the README and real code are in same repo therefore more likely to be in-sync), but instead we chose to just point to the wiki from README, so that we maintain only one set of links.


In order to use this token acquisition method, you need to configure a service principal. Please follow [this walkthrough](https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/).

Find the `Main logic` part in the [sample](sample/client_credentials_sample.py#L46-L55).

### Acquire Token with client certificate
A service principal is also required.
Find the `Main logic` part in the [sample](sample/certificate_credentials_sample.py#L55-L64).

### Acquire Token with Refresh Token
Find the `Main logic` part in the [sample](sample/refresh_token_sample.py#L47-L69).

### Acquire Token with device code
Find the `Main logic` part in the [sample](sample/device_code_sample.py#L49-L54).

### Acquire Token with authorization code
Find the `Main logic` part in the [sample](sample/website_sample.py#L107-L115) for a complete bare bones web site that makes use of the code below.

## Logging

#### Personal Identifiable Information (PII) & Organizational Identifiable Information (OII)

Starting from ADAL Python 0.5.1, by default, ADAL logging does not capture or log any PII or OII. The library allows app developers to turn this on by configuring the `enable_pii` flag on the AuthenticationContext. By turning on PII or OII, the app takes responsibility for safely handling highly-sensitive data and complying with any regulatory requirements.
## Samples and Documentation
We provide a full suite of [sample applications on GitHub](https://github.com/azure-samples?utf8=%E2%9C%93&q=active-directory&type=&language=) to help you get started with learning the Azure Identity system. This includes tutorials for native clients and web applications. We also provide full walkthroughs for authentication flows such as OAuth2, OpenID Connect and for calling APIs such as the Graph API.

```python
//PII or OII logging disabled. Default Logger does not capture any PII or OII.
auth_context = AuthenticationContext(...)
You can find the relevant samples by scenarios listed in this [wiki page for acquiring tokens using ADAL Python](https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/Acquire-tokens#adal-python-apis-for-corresponding-flows).

//PII or OII logging enabled
auth_context = AuthenticationContext(..., enable_pii=True)
```
The documents on [Auth Scenarios](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios#application-types-and-scenarios) and [Auth protocols](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-openid-connect-code) are recommended reading.

## Samples and Documentation
We provide a full suite of [sample applications on GitHub](https://github.com/azure-samples?utf8=%E2%9C%93&q=active-directory&type=&language=) and an [Azure AD developer landing page](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-developers-guide) to help you get started with learning the Azure Identity system. This includes tutorials for native clients and web applications. We also provide full walkthroughs for authentication flows such as OAuth2, OpenID Connect and for calling APIs such as the Graph API.
## Versions

It is recommended to read the [Auth Scenarios](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios) doc, specifically the [Scenarios section](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios#application-types-and-scenarios). For some topics about registering/integrating an app, checkout [this doc](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications). And finally, we have a great topic on the Auth protocols you would be using and how they play with Azure AD in [this doc](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-openid-connect-code).
This library follows [Semantic Versioning](http://semver.org/).

While Python-specific samples will be added into the aforementioned documents as an on-going effort, you can always find [most relevant samples just inside this library repo](https://github.com/AzureAD/azure-activedirectory-library-for-python/tree/dev/sample).
You can find the changes for each version under [Releases](https://github.com/AzureAD/azure-activedirectory-library-for-python/releases).

## Community Help and Support

Expand All @@ -80,29 +41,8 @@ If you find a security issue with our libraries or services please report it to

## Contributing

All code is licensed under the MIT license and we triage actively on GitHub. We enthusiastically welcome contributions and feedback. You can clone the repo and start contributing now.
All code is licensed under the MIT license and we triage actively on GitHub. We enthusiastically welcome contributions and feedback. Please read the [contributing guide](./contributing.md) before starting.

## We Value and Adhere to the Microsoft Open Source Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.

## Quick Start

### Installation

``` $ pip install adal ```

### http tracing/proxy
If you need to bypass self-signed certificates, turn on the environment variable of `ADAL_PYTHON_SSL_NO_VERIFY`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, this particular line was the only place we document this behavior. If we are going to remove it here, do we plan to document it somewhere in the wiki then?

PS: We did mention it recently in API reference doc. But I assume DevOps will not necessarily read API Reference doc. I could be wrong, though.

Copy link
Contributor Author

@navyasric navyasric May 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This content is moved to the Basics page of the Wiki and I'll be linking to this page under installation part of Readme.



## Note

### Changes on 'client_id' and 'resource' arguments after 0.1.0
The convenient methods in 0.1.0 have been removed, and now your application should provide parameter values to `client_id` and `resource`.

2 Reasons:

* Each adal client should have an Application ID representing a valid application registered in a tenant. The old methods borrowed the client-id of [azure-cli](https://github.com/Azure/azure-xplat-cli), which is never right. It is simple to register your application and get a client id. You can follow [this walkthrough](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications). Do check out if you are new to AAD.

* The old method defaults the `resource` argument to 'https://management.core.windows.net/', now you can just supply this value explictly. Please note, there are lots of different azure resources you can acquire tokens through adal though, for example, the samples in the repository acquire for the 'graph' resource. Because it is not an appropriate assumption to be made at the library level, we removed the old defaults.
2 changes: 1 addition & 1 deletion adal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

# pylint: disable=wrong-import-position

__version__ = '0.6.0'
__version__ = '1.0.0'

import logging

Expand Down
6 changes: 3 additions & 3 deletions adal/authentication_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class AuthenticationContext(object):

def __init__(
self, authority, validate_authority=None, cache=None,
api_version='1.0', timeout=None, enable_pii=False, verify_ssl=None, proxies=None):
api_version=None, timeout=None, enable_pii=False, verify_ssl=None, proxies=None):
'''Creates a new AuthenticationContext object.

By default the authority will be checked against a list of known Azure
Expand All @@ -68,9 +68,9 @@ def __init__(
AuthenticationContexts.
:param api_version: (optional) Specifies API version using on the wire.
Historically it has a hardcoded default value as "1.0".
Developers are now encouraged to set it as None explicitly,
Developers have been encouraged to set it as None explicitly,
which means the underlying API version will be automatically chosen.
In next major release, this default value will be changed to None.
Starting from ADAL Python 1.0, this default value becomes None.
:param timeout: (optional) requests timeout. How long to wait for the server to send
data before giving up, as a float, or a `(connect timeout,
read timeout) <timeouts>` tuple.
Expand Down
1 change: 0 additions & 1 deletion adal/token_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ def get_token_with_authorization_code(self, authorization_code, client_secret, c
self._cache_driver.add(token)
return token


def _get_token_with_refresh_token(self, refresh_token, resource, client_secret):

self._log.info("Getting a new token from a refresh token")
Expand Down
2 changes: 1 addition & 1 deletion sample/certificate_credentials_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_private_key(filename):
turn_on_logging()

### Main logic begins
context = adal.AuthenticationContext(authority_url, api_version=None)
context = adal.AuthenticationContext(authority_url)
key = get_private_key(sample_parameters['privateKeyFile'])

token = context.acquire_token_with_client_certificate(
Expand Down
2 changes: 1 addition & 1 deletion sample/client_credentials_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def turn_on_logging():
### Main logic begins
context = adal.AuthenticationContext(
authority_url, validate_authority=sample_parameters['tenant'] != 'adfs',
api_version=None)
)

token = context.acquire_token_with_client_credentials(
RESOURCE,
Expand Down
2 changes: 1 addition & 1 deletion sample/device_code_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def turn_on_logging():
#turn_on_logging()

### Main logic begins
context = adal.AuthenticationContext(authority_url, api_version=None)
context = adal.AuthenticationContext(authority_url)
code = context.acquire_user_code(RESOURCE, clientid)
print(code['message'])
token = context.acquire_token_with_device_code(RESOURCE, code, clientid)
Expand Down
2 changes: 1 addition & 1 deletion sample/refresh_token_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def turn_on_logging():
### Main logic begins
context = adal.AuthenticationContext(
authority_url, validate_authority=sample_parameters['tenant'] != 'adfs',
api_version=None)
)

token = context.acquire_token_with_username_password(
RESOURCE,
Expand Down
4 changes: 2 additions & 2 deletions sample/website_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def do_GET(self):
token_response = self._acquire_token()
message = 'response: ' + json.dumps(token_response)
#Later, if the access token is expired it can be refreshed.
auth_context = AuthenticationContext(authority_url, api_version=None)
auth_context = AuthenticationContext(authority_url)
token_response = auth_context.acquire_token_with_refresh_token(
token_response['refreshToken'],
sample_parameters['clientId'],
Expand All @@ -109,7 +109,7 @@ def _acquire_token(self):
if state != cookie['auth_state'].value:
raise ValueError('state does not match')
### Main logic begins
auth_context = AuthenticationContext(authority_url, api_version=None)
auth_context = AuthenticationContext(authority_url)
return auth_context.acquire_token_with_authorization_code(
code,
REDIRECT_URI,
Expand Down
3 changes: 2 additions & 1 deletion tests/test_api_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def test_api_version_default_value(self):
warnings.simplefilter("always")
context = adal.AuthenticationContext(
"https://login.windows.net/tenant")
self.assertEqual(context._call_context['api_version'], '1.0')
self.assertEqual(context._call_context['api_version'], None)
self.assertEqual(len(caught_warnings), 0)
if len(caught_warnings) == 1:
# It should be len(caught_warnings)==1, but somehow it works on
# all my local test environment but not on Travis-CI.
Expand Down
2 changes: 1 addition & 1 deletion tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def val_exists(val):
def match_standard_request_headers(mock_request):
matches = []
matches.append(mock_request.headers.get('x-client-SKU', None) == 'Python')
matches.append(mock_request.headers.get('x-client-Ver', "").startswith('0.'))
assert mock_request.headers.get('x-client-Ver') is not None
matches.append(mock_request.headers.get('x-client-OS', None) != None)
matches.append(mock_request.headers.get('x-client-CPU', None) != None)
request_id = correlation_id_regex.match(mock_request.headers.get('client-request-id'))
Expand Down