Skip to main content

I am facing authorization issues with my django app. 

Context: I have a django app that provides an option for the users to authorize their miro accounts and access their miro boards within the app. It has the following view for authorization and callbacks:
 

@login_required

def miro_authorize(request):

    profile = request.user.profile

 

    if not profile.miro_client_id or not profile.miro_client_secret:

        messages.error(request, "Please update your Miro Client ID and Client Secret in your profile.")

        return redirect('profile')

   

    # Redirect the user to Miro's OAuth2 authorization page

    redirect_uri = settings.MIRO_REDIRECT_URI

    scope = "boards:write boards:read"

 

    miro_auth_url = f"https://miro.com/oauth/authorize?response_type=code&client_id={profile.miro_client_id}&redirect_uri={redirect_uri}&scope={scope}"

   

    return redirect(miro_auth_url)

 

@login_required

def miro_callback(request):

    code = request.GET.get('code')

    profile = request.user.profile

 

    if not code:

        messages.error(request, "No authorization code found.")

        return redirect('profile')

 

    # Exchange code for an access token

    token_url = "https://api.miro.com/v1/oauth/token"

    redirect_uri = settings.MIRO_REDIRECT_URI

    data = {

        'grant_type': 'authorization_code',

        'code': code,

        'redirect_uri': redirect_uri,

        'client_id': profile.miro_client_id,

        'client_secret': profile.miro_client_secret

    }

 

    try:

        # Step 1: Fetch Access Token

        token_response = requests.post(token_url, data=data)

        token_response.raise_for_status()

        token_data = token_response.json()

 

        # Save the tokens

        profile.miro_access_token = token_data.get('access_token')

        profile.miro_refresh_token = token_data.get('refresh_token')

        profile.save()

 

        # Step 2: Fetch User's Miro ID from /v2/me

        headers = {

            'Authorization': f'Bearer {profile.miro_access_token}'

        }

        user_info_url = "https://api.miro.com/v1/users/me"

        user_response = requests.get(user_info_url, headers=headers)

        user_response.raise_for_status()

        user_data = user_response.json()

 

        # Save the Miro User ID to the profile

        profile.miro_user_id = user_data.get('id')  # Extract user ID

        profile.save()

 

        # Step 3: Fetch user-specific boards

        user_boards_url = "https://api.miro.com/v2/boards"

        boards_response = requests.get(user_boards_url, headers=headers)

        boards_response.raise_for_status()

        boards_data = boards_response.json()

 

        # Filter boards by 'createdBy' matching the user's Miro ID

        user_owned_boards =  

            board for board in boards_data.get('data', Â])

            if board.get('createdBy') == profile.miro_user_id

        ]

 

        # Optionally, store filtered boards in the profile or session

        request.sessionc'miro_boards'] = user_owned_boards

 

        messages.success(request, "Miro account connected successfully! Your boards are now visible.")

        return redirect('profile')

 

    except requests.exceptions.RequestException as e:

        messages.error(request, f"Error connecting to Miro: {str(e)}")

        return redirect('profile')



The issue that I am facing is, my users are able to see the teams and the boards that I created for myself in the app. Ideally, they should be seeing only the teams and the boards that they created. Can anyone help me identify what am I doing wrong?

For additional context, here is the Django template:

 

<div class="row g-4 py-5">

            <div class="col d-flex align-items-start">

                <div>

                    <h2 class="mb-3 border-bottom" style="color: black">Your Conversational Flows</h2>

                    <p class="col d-flex align-items-start">To see your conversational flows or to create one:</p>

                    <p class="col d-flex align-items-start"><a href="{% url 'miro_authorize' %}">Authorize Miro</a></p>

                </div>

            </div>

Following are the Django Urls:

 

path('miro/authorize/', miro_authorize, name='miro_authorize'),

path('miro/callback/', miro_callback, name='miro_callback'),

Following is my user profile model:

 

# Create your models here.

class Profile(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)

    miro_client_id = models.CharField(max_length=255, blank=True, null=True, verbose_name="Miro Client ID")

    miro_client_secret = models.TextField(blank=True, null=True, verbose_name="Miro Client Secret")

    miro_access_token = models.CharField(max_length=255, null=True, blank=True)

    miro_refresh_token = models.CharField(max_length=255, null=True, blank=True)

    miro_team_id = models.CharField(max_length=255, blank=True, null=True)

    miro_user_id = models.CharField(max_length=255, blank=True, null=True, verbose_name="Miro User ID")  # New field

 

 

Hi rahul.pod,

Thank you for sharing the details of your issue. It looks like the root cause of the problem is related to the use of deprecated v1 endpoints and how you’re filtering boards.

Here’s what you can try to do to address this:

  1. Avoid using deprecated v1 endpoints
    Most v1 endpoints are deprecated and will be sunsetted soon. However, you can still use the v1/oauth-token endpoint for specific purposes, like retrieving the user's ID.

  2. Retrieve the user's ID
    Use the v1/oauth-token endpoint (GET request) to fetch the authenticated user's ID. This ID is critical for filtering boards in the v2 API. Example:

    GET https://api.miro.com/v1/oauth-token

    Authorization: Bearer <access_token>

    This will return the user’s ID.

  3. Filter boards by owner_id
    Once you have the user ID, use the owner_id parameter with the GET /v2/boards endpoint to fetch only the boards created by that specific user.

    This ensures your users only see boards that they’ve created.

Hope this helps!

Ruslan


Reply