Re: [Ace] AD review of draft-ietf-ace-oauth-authz-24

Ludwig Seitz <> Wed, 13 November 2019 12:55 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 16A081208C1; Wed, 13 Nov 2019 04:55:54 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.9
X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id Ya3_aB_Que6X; Wed, 13 Nov 2019 04:55:49 -0800 (PST)
Received: from ( []) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 19BE71208A9; Wed, 13 Nov 2019 04:55:49 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901;; cv=none; b=DlHcX/7GVvRM5nuAxkzYUVD4hU06j85eGUKZfQcKfMJ8jbCbO2Jq85NSeatCOncCVjDapF6P4nZvFvsq/56wCNwS4AFFSPf0upebyJu2Z4666zSO+efRjzz9qXOqmTmwG3zdxGEFM0oXpvBVT2aczkqJUvh9m9cKjIrE+rYgWYZqknfx9IfwMEllibJ2YntkqB3KVK1XrGIkHxCTUT+5nAY84PJg3rG22WG5OH6eLG7Qg74ONVKVzhTwhR4+3P0MWvbhps4L683EASqACPWPL5LQZ/bffd6K2pTD9vXRcwtTOlu3HVhTjd//07BvU9+8TVomWTYSNzWgXuJ6Vp2dZg==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=iDFMi1iL0UZSkJ0CH3eySBLWE+Ip9io1hDyDmmRJNZM=; b=NDa9MjF4isWeADObSlWugXskn2k1rt7QvqiYwe8T+D85UOZJjFo0JKawJM53LdiwitCry37o3ePxFM+AYhE4mWE57Z3j3BpXjZDxfSHzFUrxsSxSm7ClKa+39EQADpOEHC+LJlfgNlXHgHXP1+DK23WDP/m4MIzQ+qXdgHrSq8DIGnnYMwHMxlcjf6I00kCIhsplUn+BGrrxvZ400zwqDpxSS//HRzE5CveUmJifxN731b7s7igLCIHnSi7zQ4ZfrfnEFqK0waPH5dRL3g3b6Fao1+6T6nBnRGK3vkq0QtttG8mKj2ATLfFO3YiQxFaCSk+CKNQV5vO0wNq83hieUQ==
ARC-Authentication-Results: i=1; 1; spf=pass (sender ip is; dmarc=pass (p=none sp=none pct=100) action=none; dkim=none (message not signed); arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=selector1-RISEcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=iDFMi1iL0UZSkJ0CH3eySBLWE+Ip9io1hDyDmmRJNZM=; b=UeFa9/9EKP3VUWwZYNUnwjQGPsVug6CV1X3fnqMvdJIdKmSZ/U+E7hKmnJc8X4UXJC7CP8LZg4Xq8QJEvMibmDus4uD8UIh7rTanc2Iy029mlw9xcXnMGu8hihTEskxKGHc2jc48ZO8YqHIbG5zoNqSigT1cc7qtubLYZ3LU1Pw=
Received: from VI1P18901CA0023.EURP189.PROD.OUTLOOK.COM (2603:10a6:801::33) by HE1P189MB0505.EURP189.PROD.OUTLOOK.COM (2603:10a6:7:61::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2430.20; Wed, 13 Nov 2019 12:55:45 +0000
Received: from (2a01:111:f400:7e05::206) by (2603:10a6:801::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2451.22 via Frontend Transport; Wed, 13 Nov 2019 12:55:45 +0000
Authentication-Results: spf=pass (sender IP is;; dkim=none (message not signed) header.d=none;; dmarc=pass action=none;
Received-SPF: Pass ( domain of designates as permitted sender); client-ip=;;
Received: from ( by ( with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2451.23 via Frontend Transport; Wed, 13 Nov 2019 12:55:45 +0000
Received: from [] ( by ( with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 13 Nov 2019 13:55:44 +0100
To: Benjamin Kaduk <>
CC: <>, <>
References: <> <> <>
From: Ludwig Seitz <>
Message-ID: <>
Date: Wed, 13 Nov 2019 13:55:44 +0100
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0
MIME-Version: 1.0
In-Reply-To: <>
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="------------ms010201090200090102070400"
X-Originating-IP: []
X-ClientProxiedBy: ( To (
X-EOPAttributedMessage: 0
X-Forefront-Antispam-Report: CIP:; IPV:NLI; CTRY:SE; EFV:NLI; SFV:NSPM; SFS:(10009020)(4636009)(51444003)(43544003)(199004)(189003)(33964004)(26005)(54906003)(446003)(70206006)(16526019)(476003)(356004)(126002)(235185007)(2171002)(86362001)(8936002)(4326008)(7736002)(6916009)(31686004)(53546011)(44832011)(5660300002)(31696002)(336012)(486006)(58126008)(186003)(11346002)(70586007)(22756006)(305945005)(106002)(30864003)(71190400001)(76176011)(40036005)(2906002)(2616005)(386003)(6246003)(498600001)(65806001)(65956001)(36756003)(8676002)(229853002)(22746008)(6306002)(81166006)(16576012)(81156014)(6116002)(3846002)(568964002)(966005)(5024004)(14444005)(16586007); DIR:OUT; SFP:1101; SCL:1; SRVR:HE1P189MB0505;; FPR:; SPF:Pass; LANG:en; PTR:InfoDomainNonexistent; A:1; MX:1;
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id: cd4d73db-724d-4816-aec7-08d76838cc4a
X-MS-TrafficTypeDiagnostic: HE1P189MB0505:
X-Microsoft-Antispam-PRVS: <HE1P189MB0505BA082D4B2A92A5C3AEC082760@HE1P189MB0505.EURP189.PROD.OUTLOOK.COM>
X-MS-Oob-TLC-OOBClassifiers: OLM:7691;
X-Forefront-PRVS: 0220D4B98D
X-MS-Exchange-SenderADCheck: 1
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: QWIvrOP6vwgGfHLrRtpsOGrDd97v+OuEgRe4fqQHpmEqlAg0BmAkCs4PD1vbmJBhve7PFPg236z2wQIhoQM46HUSojylREBEn3bCFU+ZTHNhxKXXo87UQW9YpUUC7j4aLUXP351YDUjvLW8YwGPhihQnAh6/bWhOJx+M6LUJSzw2DHAiEsINKytsXRDfm140IP9G+++NIVhfKve6Ub2kQPG1MzwfQLZBnEzRntzQZjQIYQsZIBjy0B9mWl0mPrKXRWJOfrQUCwF6WI4dRWRMJlqD4/0UnFh19F4tnsAH7XWcFO6OfdwW/57fA44vBMxE/XZ3S6L2dJtjAXKxDviewif1MvlpODvOex9VkZf470VaD1xD2Et6IC09lqhOdlsthePiyHfKr84LFoY6oGwz53rR79y+63LxsSaqqkrxUnnu9Ck2dr2g7zh8rGK2vFM4
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Nov 2019 12:55:45.0497 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: cd4d73db-724d-4816-aec7-08d76838cc4a
X-MS-Exchange-CrossTenant-Id: 5a9809cf-0bcb-413a-838a-09ecc40cc9e8
X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5a9809cf-0bcb-413a-838a-09ecc40cc9e8; Ip=[]; Helo=[]
X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem
X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1P189MB0505
Archived-At: <>
Subject: Re: [Ace] AD review of draft-ietf-ace-oauth-authz-24
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "Authentication and Authorization for Constrained Environments \(ace\)" <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 13 Nov 2019 12:55:54 -0000

On 10/11/2019 04:28, Benjamin Kaduk wrote:

>>> 1.)
>>> Perhaps the most far-reaching changes needed
>>> will be to rename the "profile" claim, since that has already been
>>> allocated to OIDC Core for a very different usage.
>> [LS] FIXED. I renamed the "profile" claim and parameters to "ace_profile"
>> Note that this will require changes in all of the profile drafts as well.
> Indeed.  It would be great if someone (the chairs? Other volunteers are
> surely welcome) could make a list of changes that affect the profile
> documents, and make a pass over each in turn to find the affected areas.

Mostly a search and replace of "profile" with "ace_profile" would be in 
order, perhaps with a subsequent proof reading that nothing was borked 
up in the process.

I can do this, but sadly not before IETF.

>>> 6.)
>>> Section 1
>>>     Authorization is the process for granting approval to an entity to
>>>     access a resource [RFC4949].  The authorization task itself can best
>>>     be described as granting access to a requesting client, for a
>>>     resource hosted on a device, the resource server (RS).  This exchange
>>> I had to pause for a while after reading this and ponder whether I
>>> agreed with it.  I think that my reticence stems from some friction
>>> between the most generic abstract definition of "resource" and a more
>>> specific one used in the web/HTTP world and, to a lesser extent, the
>>> world of URIs and URNs in general.  The resources we are discussing here
>>> are not always specific named resources, but can also refer to
>>> attributes or capabilities mediated by a RS; similarly, we may be
>>> creating/modifying named resources as part of the resource access
>>> performed by a client in the OAuth model.  I don't think it's wise to
>>> diverge from the RFC 4949 definition just yet, but am still considering
>>> whether adding some additional clarifying text here is worthwhile.
>> [LS] I would argue that this specification is applicable even to the wider
>> definition of "resource" that you are thinking of. Since OAuth 2.0 leaves
> Oh, I agree, and was not intending to say otherwise with my comments above.
> Rather, I was considering that some [other] readers might see the word
> "resource" and go straight to "web resource named by URI", and wondering if
> we could reword slightly to avoid that.
>  >> the definition of "scope" up to the specific applications, and the ACE
>> framework does not change this, we can deal with both web/HTTP/CoAP
>> resources
>> (named by URIs or URNs) and any other type of resources where the
>> application
>> can map the resource in question to a set of scopes.
>> I am therefore inclined to say that this section is fine, but I'd be glad to
>> hear the result of your considerations on that matter.
> I see three potential options so far:
> (1) no change
> (2) in the first sentence, s/resource/generic resource/
> (3) add a new sentence as the third sentence, similar to "This resource
> might be a Web or similar resource addressed by URI, but in general can be
> a more generic or abstract resource provided by the RS".
> I'm happy to advance the document with any of those three (and probably
> with other versions, if any arise).

I'll go with option 2 which seems to be a fine compromise with minimal 
text breakage.

>>> 16.)
>>> Section 3.2
>>>     One application of COSE is OSCORE [I-D.ietf-core-object-security],
>>>     which provides end-to-end confidentiality, integrity and replay
>>>     protection, and a secure binding between CoAP request and response
>>>     messages.  In OSCORE, the CoAP messages are wrapped in COSE objects
>>>     and sent using CoAP.
>>>     This framework RECOMMENDS the use of CoAP as replacement for HTTP for
>>>     use in constrained environments.
>>> Do we have a reason to mention OSCORE if we're not going to make a
>>> recommendation about its use?
>> [LS] We also mention DTLS and TLS without making any recommendation about
>> which to use. I would suggest to either remove all of it or to add a
>> sentence
>> noting that this is an enumeration of some security options, and the choice
>> depends on the specific application scenario.
> Adding a sentence feels like a slightly better option to me, though it
> could easily go either way.

>>> 19.)
>>> Section 5
>>>     Credential Provisioning
>>>        For IoT, it cannot be assumed that the client and RS are part of a
>>>        common key infrastructure, so the AS provisions credentials or
>>>        associated information to allow mutual authentication.  These
>>>        credentials need to be provided to the parties before or during
>>>        the authentication protocol is executed, and may be re-used for
>>>        subsequent token requests.
>>> nit: either "before or during the execution of the authentication
>>> protocol" or "before or during the authentication protocol's execution".
>>> And just to double-check that we mean the authentication protocol of
>>> provisioning in the last sentence, not the authorization protocol that
>>> occurs between the client and RS.
>> [LS] The whole last sentence was a bit off. I would suggest:
>> "The resulting security association between client and RS may then be
>> re-used
>> by binding these credentials to additional access tokens." Does that
>> sound better?
> That definitely reads more coherently, yes.  It makes implicit the fact
> that there is an authentication protocol that gets run, which is probably
> okay, and I'm not sure whether "additional" is quite in line with the way
> the previous sentence is formulated.  (Maybe it makes more sense in
> context, which I don't have in front of me right now.)

You are right that was still off. Fixed that now.

>>> 39.)
>>>     Refresh tokens are typically not stored as securely as proof-of-
>>>     possession keys in requesting clients.  Proof-of-possession based
>>>     refresh token requests MUST NOT request different proof-of-possession
>>>     keys or different audiences in token requests.  Refresh token
>>>     requests can only use to request access tokens bound to the same
>>>     proof-of-possession key and the same audience as access tokens issued
>>>     in the initial token request.
>>> This is perhaps something of a philosophical question, but if a refresh
>>> token is only usable at the token endpoint, in some sense its audience
>>> is definitionally the AS.  So there's a little bit of a mismatch in
>>> treating it as having the audience value that the access tokens issued
>>> from it will have.  I don't know the background for audience-restriced
>>> refresh tokens in regular OAuth 2.0, though, so hopefully someone can
>>> educate me.
>> [LS] I'm equally confused. I suggest that Hannes or one of the other OAuth
>> experts give us a hint on that one.
> [We had some stab at this in the other thread, but additional input might
> still be in order]

Let's hear with OAuth people in Singapore.

>>> 58.)
>>>     Profiles MUST specify whether the authz-info endpoint is protected,
>>>     including whether error responses from this endpoint are protected.
>>>     Note that since the token contains information that allow the client
>>>     and the RS to establish a security context in the first place, mutual
>>>     authentication may not be possible at this point.
>>> We'll need some careful reasoning about this for the security
>>> considerations, since the authz-info transaction can impact what profile
>>> the RS thinks is in use.  E.g., whether a network attacker could
>>> cause the client to think that a different (vulnerable) profile is in
>>> use than the one the RS expects to use.
>> [LS] Noted. Do you think the reasoning in section 6.5 needs to be extended?
> I think we should add some more text, yes.
> Specifically, we should mention that the authz-info interaction can affect
> what profile RS will use (e.g., via "ace_profile"), and that profile
> developers should be conscious of the risk of downgrade attacks that
> involve other profile types.  (Am I reading this right that the client will
> know what profile to use by the time it is ready to post to the authz-info
> endpoint and that the response will not change what profile the client
> uses?  Specifically, even if a client supports multiple profiles that use
> different methods for token transport, a client is not going to try one
> method/profile and then fall back to a different one if the first one
> (transiently) fails?)

I'm not sure how you would mount such a downgrade attack. The client 
receives the profile to use either by implicit configuration or 
explicitly through the "profile" parameter from the AS.
If the client does not receive a "profile" parameter and has no implicit 
profile configured this is an error.

The RS either has the profile pre-configured or receives it via an 
authenticated "profile" claim in the access token (again if the claim is 
missing and no pre-configured profile exists this is an error). Even 
though the token is sent to authz-info over an insecure channel and the 
client is not yet authenticated, the access token itself is, and 
therefore I find it hard to see how an attacker would trick the RS to 
use a different profile.

>>> 65.)
>>>        specification defines the following approach: The claim "exi"
>>>        ("expires in") can be used, to provide the RS with the lifetime of
>>>        the token in seconds from the time the RS first receives the
>>>        token.  This approach is of course vulnerable to malicious clients
>>>        holding back tokens they do not want to expire.  Such an attack
>>> It also has suboptimal behavior if the RS loses state (e.g., by
>>> rebooting), and possibly requires the RS to store indefinitely all
>>> tokens with an "exi" value.  I have mixed feelings about specifying it
>>> at all, though I concede it probably does have some value.  Regardless,
>>> I think a dedicated subsection in the security considerations is in
>>> order.
>> [LS] We wanted to provide some solution for expiring tokens for RSes
>> that have
>> no connectivity and no synchronized clocks. Using the "exp" claim in
>> such cases
>> would have pretty unpredictable results.
>> I have extended section 6.3 in the security considerations to go into
>> the detail
>> of "exi", please have a look if this covers the necessary issues.
> I think we should also say something about the amount of such persistent
> storage potentially growing without bound, as those counters (or some
> similar indication) are the only thing that will cause the RS to reject
> tokens that have been used the requisite number of times.  So, RS state
> requirements grows with the number of 'exi'-bearing tokens that are issued
> for them.  I suppose a bloom filter might be a way out, though...

I don't see why storage requirements would grow more compared to regular 
tokens with the "exp" claim. The way exi is intended to be implemented 
is as follows:

1. C ---Token(exi=100)---> RS  (internal_clock=54645)
2. RS generates a new 'exp' for the token, sets it to 54745 and discards 
the exi claim.
3. RS expires token according to internal clock (i.e. at 54745)

If you send the RS a lot of tokens it will eventually exhaust its 
memory, but that would happen with regular exp claims as well if the 
attacker can craft/obtain enough tokens with sufficiently long lifetime.
Note that these would have to be tokens for different clients, since the 
framework currently recommends to only store one token per client.

The advantage for the attacker with exi is that it could hold back any 
tokens without having to worry about the expiration, but it would still 
have to hoard enough tokens for different clients, all applicable to the 
RS in order to exhaust the RS's storage.

>>> 68.)
>>>     o  The client performs an introspection of the token.  Although this
>>>        is not explicitly forbidden, how exactly a client does
>>>        introspection is not currently specified for OAuth.
>>> I'm pretty sure this is overtaken by events (sorry for my part in
>>> that!).  E.g., draft-ietf-oauth-jwt-introspection-response discusses
>>> clients doing introspection, and even RFC 7662 itself discusses using a
>>> client secret to authenticate to the introspection endpoint.  I think
>>> there's another document between those two that's also relevant, but
>>> can't find it right now
>> [LS] I am not so sure. When reading the fine print in both RFC 7662 and
>> draft-ietf-oauth-jwt-introspection-response, I find that when they mention
>> the term "client", they refer to the protected resource / RS as being a
>> client of
>> the AS introspection endpoint.  A client holding an access token and
>> performing introspection is never explicitly mentioned in both
>> documents, to my best
>> knowledge.
> It seems like we should try to check on this in Singapore, while the usual
> suspects are easily at hand.

Yes together with the other OAuth questions.

>>> 78.)
>>> Section 6.1
>>> I think we should have a little bit more discussion about what attacks
>>> are possible even when a client hard-codes a list of trustworthy ASes,
>>> e.g., when a device in one AS's purview is compromised and tries to get
>>> the client to use a different (possibly also compromised, or maybe just
>>> buggy) AS than the one that's supposed to be responsible for the device
>>> in question.  In short, yes, spoofing is only possible within that set
>>> of trusted ASes, but spoofing can still cause problems.
>> [LS] I have added some text in section 6.4 Please have a look if this
>> covers what you were aiming at.
> That's pretty good, thanks!
> I'd prefer to also have (in the second sentence of the second paragraph) a
> mention about what an AS (in the hard-coded list) would do when receiving
> the incorrect request from the misdirected client, though.
> (Also, nit, s/ redentials/ credentials/)

Done and fixed.

>>> 79.)
>>> Are there any AS parameters other than URI that might be useful for an
>>> out-of-band-configured list of valid values?
>> [LS] One might want to include the public key or certificate of the AS.
>> Do you want us to expand this section to include such parameters?
> I'd consider adding another sentence like "Information used to authenticate
> the AS, such as a public key or certificate fingerprint, might be
> provisioned alongside an AS's URI, depending on the deployment scenario".
> What do you think?


>>> 88.)
>>> Section 8.3
>>>     Name  The OAuth Error Code name, refers to the name in Section 5.2.
>>>        of [RFC6749], e.g., "invalid_request".
>>> We should refer to the OAuth registry as the authority on names, not the
>>> immutable RFC.  (Similarly for the other mappings registries; I won't
>>> repeat it each time, though for the later ones we're already doing the
>>> right thing.)
>> [LS] This is interesting. The referenced section (5.2 of RFC6749) is not
>> mirrored in any IANA registry. I have put the question to the OAuth WG.
> IIRC, you filed for this and I
> submitted a registration request at
> .  It's been more than two weeks, so I should follow up there...

Ok, I'll wait to hear more.

>>> 97.)
>>> Section 10.1
>>> We may get some debate about whether IANA registries are properly
>>> Normative of Informative references, but we can wait for that to happen
>>> -- no need to do anything now.
>> [LS] Noted. Does the AD have a position on this?
> I think there's a reasonable argument for keeping them as normative.  We
> probably see them as informative more often (in general), though, probably
> because people are concerned about having downrefs to something that's not
> a standards-track RFC (which would happen due to a misunderstanding of the
> rules surrounding downrefs, IMO).

Ok no action taken at this point.

>>> 98.)
>>> Section 10.2
>>> If we're using RFC 4949 for terminology definitions, I think that makes
>>> it a normative reference.
>>> If we REQUIRE CBOR when used with CoAP, that also feels like a normative
>>> reference.
>>> I also think 7519 needs to be normative, since we mandate some of its
>>> processing rules.
>> [LS] RFC 4949 is informational, so it cannot be normative. I would argue
>> that we are just using it to clarify the meaning of our terminology.
> It's okay to have a normative reference to an informational document; we
> just need to call it out in the IETF LC announcement (which the
> tooling/secretariat should take care of "automagically").
> Furthermore, RFC 4949 is already listed at
> as an "acceptable downref", so we
> don't even have to do that, in this case.

Ok I made RFC 4949 normative, I didn't know about the "acceptable 
downref" arrangement with the secretariat.

> If you want to get a new revision up to make these last few changes during
> the blackout period, I'm happy to approve a manual posting by the
> secretariat.  (OTOH, since IETF LCs that overlap with the meeting week get
> extended automatically, it wouldn't necessarily get the document on an IESG
> telechat any sooner.)

I have made a few changes, but there are still some points to discuss. 
If you think the updates still warrant a new submission, I can do a 
submission with manual approval.


Ludwig Seitz, PhD
Security Lab, RISE
Phone +46(0)70-349 92 51